Я бы посоветовал просто не делать этого. Это не обязательно то, что вы хотите услышать, но особенно при микшировании с TransactionScope
точки сохранения не являются хорошей идеей. TransactionScope
s может быть вложенным, но первый откат обрекает все , и фиксация происходит только в самой внешней транзакции.
В большинстве сценариев, о которых я могу подумать, лучше очистить данные сначала . Вы можете (и должны) также использовать ограничения для сети безопасности, но если вы нажмете эту сеть безопасности, допустите большие проблемы и откатитесь на все.
Пример вложенных транзакций:
public void DebitCreditAccount(int accountId, decimal amount, string reference)
{
using(var tran = new TransactionScope())
{
// confirm account exists, and update estimated balance
var acc = db.Accounts.Single(a => a.Id == accountId);
acc.BalanceEstimate += amount;
// add a transaction (this defines the **real** balance)
db.AccountTransactions.InsertOnSubmit(
new AccountTransaction {
AccountId = accountId, Amount = amount,
Code = amount >= 0 ? "C" : "D",
Reference = reference });
db.SubmitChanges();
tran.Complete();
}
}
public void Transfer(int fromAccountId, int toAccountId,
decimal amount, string reference)
{
using(var tran = new TransactionScope())
{
DebitCreditAccount(fromAccountId, -amount, reference);
DebitCreditAccount(toAccountId, amount, reference);
tran.Complete();
}
}
В приведенном выше примере DebitCreditAccount
является атомарным - мы либо добавим транзакцию по счету и обновим расчетный баланс, либо ни один из них. Если это транзакция only , то она фиксируется в конце этого метода.
Однако в методе Transfer
мы создаем еще одну внешнюю транзакцию; мы либо выполним оба DebitCreditAccount
, либо ни . Здесь внутренняя tran.Complete()
(в DebitCreditAccount
) не не фиксирует db-транзакцию, поскольку существует внешняя транзакция. Это просто говорит: «Я счастлив». И наоборот, если либо внутренних транзакций отменяется (Dispose()
вызывается без Complete()
), то транзакция external откатывается немедленно , и эта сделка откажется от любой дополнительной работы. Транзакция external фиксируется, только если транзакция inner не была прервана, и Complete()
вызывается во внешней транзакции.