トランザクションまたはSaveChanges(false)とAcceptAllChanges()を使用しますか?

c# entity-framework transactions

質問

トランザクションを調査していfalseSaveChanges() falseを渡してエラーがなければAcceptAllChanges()呼び出す限り、トランザクションはEFで処理されfalse

SaveChanges(false);
// ...
AcceptAllChanges();

何かが悪くなったら?ロールバックする必要はありませんか。または、メソッドが範囲外になるとすぐにトランザクションは終了しますか。

トランザクションの途中で割り当てられた任意のインデント列はどうなりますか?私が悪くなる前に、他の誰かが私の後にレコードを追加したとしたら、これはIdentityの値が失われることを意味します。

私のコードで標準のTransactionScopeクラスを使用する理由はありますか?

受け入れられた回答

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)の呼び出しSaveChanges(false)が必要なコマンドをデータベースに送信している間は、コンテキスト自体は変更されないため、必要に応じて再度実行することも、必要に応じてObjectStateManagerもできます。

これは、トランザクションが実際に例外をスローした場合、どこかの各コンテキストObjectStateManager状態を再試行するかログに記録することによって、ユーザーが補償できることを意味します。

詳しくは私の ブログ記事を参照しください。


人気のある回答

EF6(Entity Framework 6以降)を使用している場合、これはSQLへのデータベース呼び出しでは変更されました。
参照してください: http : //msdn.microsoft.com/en-us/data/dn456843.aspx

context.Database.BeginTransactionを使用してください。

MSDNから:

using (var context = new BloggingContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
        try 
        { 
            context.Database.ExecuteSqlCommand( 
                @"UPDATE Blogs SET Rating = 5" + 
                    " WHERE Name LIKE '%Entity Framework%'" 
                ); 

            var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
            foreach (var post in query) 
            { 
                post.Title += "[Cool Blog]"; 
            } 

            context.SaveChanges(); 

            dbContextTransaction.Commit(); 
        } 
        catch (Exception) 
        { 
            dbContextTransaction.Rollback(); //Required according to MSDN article 
            throw; //Not in MSDN article, but recommended so the exception still bubbles up
        } 
    } 
} 


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ