使用Transactions或SaveChanges(false)和AcceptAllChanges()?

c# entity-framework transactions

我一直在調查事務,只要我將false傳遞給SaveChanges()然後如果沒有錯誤就調用AcceptAllChanges() ,它們似乎會在EF中處理它們自己:

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

如果事情變壞怎麼辦?我不必回滾,或者一旦我的方法超出範圍,交易結束了嗎?

在事務中途分配的任何indentiy列會發生什麼?我認為如果其他人在我的事情發生之前添加了一條記錄,那麼這意味著會有一個缺失的身份值。

有沒有理由在我的代碼中使用標準的TransactionScope類?

一般承認的答案

使用Entity Framework大部分時間SaveChanges()就足夠了。這會創建一個事務,或在任何環境事務中登記,並在該事務中完成所有必要的工作。

有時雖然SaveChanges(false) + AcceptAllChanges()配對很有用。

對此最有用的地方是您希望跨兩個不同的上下文執行分佈式事務。

就是這樣(壞):

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()失敗,則中止整個分佈式事務。但不幸的是,實體框架已經放棄了對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狀態來進行補償。

有關更多信息 ,請參閱我的 博文


熱門答案

如果您使用的是EF6(實體框架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合法嗎? 是的,了解原因