ほとんどの場合、Entity Frameworkを使用 SaveChanges()
場合十分です。これにより、トランザクションが作成されるか、アンビエントトランザクションに参加し、そのトランザクションで必要なすべての作業が実行されます。
SaveChanges(false) + AcceptAllChanges()
ペアリングが役立つこともあります。
これに最も役立つのは、2つの異なるコンテキスト間で分散トランザクションを実行する場合です。
すなわちこのようなもの(悪い):
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save and discard changes
context1.SaveChanges();
//Save and discard changes
context2.SaveChanges();
//if we get here things are looking good.
scope.Complete();
}
もしは context1.SaveChanges()
成功したがcontext2.SaveChanges()
、全体の分散トランザクションが中止されて失敗します。ただし、残念ながらEntity Frameworkはの変更をすでに破棄しているcontext1
ため、失敗を再生したり効果的にログに記録したりすることはできません。
ただし、コードを次のように変更すると、
using (TransactionScope scope = new TransactionScope())
{
//Do something with context1
//Do something with context2
//Save Changes but don't discard yet
context1.SaveChanges(false);
//Save Changes but don't discard yet
context2.SaveChanges(false);
//if we get here things are looking good.
scope.Complete();
context1.AcceptAllChanges();
context2.AcceptAllChanges();
}
への呼び出しによりSaveChanges(false)
、必要なコマンドがデータベースに送信されますが、コンテキスト自体は変更されないため、必要に応じてもう一度実行するか、またはObjectStateManager
ます。
これは、トランザクションが実際に例外をスローした場合、ObjectStateManager
どこかで各コンテキストの状態を再試行またはログ記録することにより、補正できることを意味します。
詳細については、私の ブログ投稿を参照してください。
SaveChanges(fase); ... AcceptAllChanges();
は、そもそもパターンがなぜだったのかを理解するのに役立ちました。上記の質問に対する受け入れられた回答がブログの作成者によってどのように記述されているかに注目してください 。そのブログは他の質問で参照されています。それはすべて一緒になります。