トランザクションまたはSaveChanges(false)およびAcceptAllChanges()を使用していますか?

StackOverflow https://stackoverflow.com/questions/815586

質問

トランザクションを調査しており、 false SaveChanges()に渡してから AcceptAllChangesを呼び出す限り、EFでトランザクションを処理しているようです。 ()エラーがない場合:

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

何かがうまくいかない場合はどうなりますか?ロールバックする必要はありませんか、メソッドがスコープから外れるとすぐにトランザクションは終了しますか?

トランザクションの途中で割り当てられたindentiy列はどうなりますか?もし私の誰かが私のものが悪くなる前に他の誰かがレコードを追加したなら、これは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)の呼び出しは必要なコマンドをデータベースに送信しますが、コンテキスト自体は変更されないため、必要に応じて再度実行するか、 ObjectStateManager 必要な場合。

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

my を参照ブログの投稿をご覧ください。

他のヒント

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
        } 
    } 
} 

一部のデータベースはdbContextTransaction.Commit()で例外をスローする可能性があるため、次の点が優れています。

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(false); 

      dbContextTransaction.Commit(); 

      context.AcceptAllChanges();
    } 
    catch (Exception) 
    { 
      dbContextTransaction.Rollback(); 
    } 
  } 
} 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top