私はトランザクションを調査してきましたが、エラーがなければ渡して呼び出す限り、false
EFSaveChanges()
でトランザクションが自動的に処理されるようです。AcceptAllChanges()
SaveChanges(false);
// ...
AcceptAllChanges();
何か問題が起きたらどうなりますか? ロールバックする必要はないのでしょうか、それともメソッドがスコープ外になるとすぐにトランザクションは終了するのでしょうか?
トランザクションの途中で割り当てられた ID 列はどうなりますか? 私のレコードが悪くなる前に他の誰かが私のレコードの後にレコードを追加した場合、ID 値が欠落することになります。
TransactionScope
コード内で標準クラスを使用する理由はありますか?
ベストアンサー1
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
どこかに記録することで補正できます。