TransactionScopeOption - требуется или требуется новое
В настоящее время у меня возникает путаница в отношении конструктора объекта TransactionScope.
Скажите, что пользователи моего сайта могут заказывать продукты. При отправке их запроса я выполняю проверку оставшегося количества слева и, если он еще больше нуля, я выполняю запрос. Затем, в конце, я уменьшаю текущую оставшуюся величину.
Весь процесс находится в транзакции, используя .NET transactionScope.
После прочтения нескольких статей об объекте .NET transactionScope, я сейчас немного запутался в значении TransactionScopeOption, которое будет использоваться для конструктора транзакцииScope.
Какое из следующих ниже подходит для случая, описанного выше:
public void ProcessRequest()
{
TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.Serializable;
using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions)) {
// DB Query to verify if quantity is still greater than zero
// DB Query to request and decrement quantity
currentScope.Complete();
}
}
ИЛИ
public void ProcessRequest()
{
TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.Serializable;
using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) {
// DB Query to verify if quantity is still greater than zero
// DB Query to request and decrement quantity
currentScope.Complete();
}
}
Обратите внимание, что приведенное выше просто упрощает мою фактическую проблему. Мне просто интересно знать правильное значение TransactionScopeOption (RequiresNew или Обязательный) для такого случая.
Спасибо за ответ.
Ответы
Ответ 1
Это зависит от того, что вы хотите, если другой метод вызывает ProcessRequest
внутри другой транзакции:
public void SomeOtherMethod() {
using (TransactionScope ts = new TrasansctionScope()) {
// Another DB action
ProcessRequest();
// Yet another DB action
}
}
Если вы хотите, чтобы ProcessRequest
использовал транзакцию, созданную с помощью SomeOtherMethod
, используйте TransactionScope.Required
. Это значение по умолчанию (и оно по-прежнему создает транзакцию, когда вы вызываете ее, не создав другую область транзакций до стека вызовов).
Если вы хотите, чтобы этот метод всегда использовал свою собственную (новую) транзакцию, используйте TransactionScope,RequiresNew
.
Ответ 2
Насколько я понимаю, ваш метод не будет вызываться в другой транзакции. Но в этом случае, вот как вы выбираете TransactionScopeOption
.
Если содержимое, записанное в базу данных ProcessRequest, не может быть отменено каким-либо вызывающим абонентом, используйте RequiresNew
, который запускает новую транзакцию parallel, созданную вызывающим (если есть), и новая транзакция не управляется вызывающим абонентом любыми способами. Лучше думать, что транзакция не может быть вложенной, либо использовать существующую транзакцию, либо создать новую. Транзакция не вложена!
Если содержимое, записанное в базу данных ProcessRequest, может быть опрокинуто, используйте Required
. Однако этот вариант не является прозрачным; caller to ProcessRequest должен знать, что ProcessRequest может откатиться, потому что, если вызываемая команда откатывает внешнюю транзакцию, вызывающий не может выполнить какую-либо операцию sql, иначе исключение "Операция недействительна для состояния транзакции". будут выброшены. Вероятно, лучше всегда проверять System.Transactions.Transaction.Current.TransactionInformation.Status
перед запуском какого-либо запроса, поскольку вы не будете знать, украден ли какой-либо вызов, и отложил его.
Вы можете найти следующую таблицу полезной.
![введите описание изображения здесь]()