2012-11-21 75 views
1

我有兩個表。第一個表格包含一些數據。第二個表包含數據更改的歷史記錄。第一個表格還包含引用上一個歷史記錄行的列。當第一個表中的行數據發生更改時,將在第二個表中插入副本,並在第一個列中引用上次數據副本的更新。爲此我使用此代碼使用事務範圍與實體框架

using (TransactionScope trn = new TransactionScope()) 
{ 
    Table1 t1=model.Table1.Where(t=>t==id).FirstOrDefault(); 
    /*update Table1 data*/ 
    Table2 t2=new Table2(); 
    t2.Table1=t1; 
    model.AddToTable2(t2); 
    /*set Table2 fields*/ 
    model.SaveChanges(); 

    t1.ref=t2.id; 
    model.SaveChanges(); 
    trn.Complete(); 
} 

使用TransactionScope保存符合數據是否可行?或者我需要使用其他方法?

回答

1

是否需要保存更改兩次?如果這些表格是相關的,您應該能夠設置導航屬性並將所有更改保存一次。在這種情況下,您不需要自行創建交易--EF會爲您創建一個交易。如果你需要保存更改兩次TransactionScope應該做的伎倆。打開時,連接將被加入事務。在代碼片段中,您不會顯示您的上下文是如何實例化的,以及連接在到達事務之前會發生什麼,因此很難判斷它是否正確。

-1

上下文類默認支持事務。但是對於每個新的上下文類實例,都會創建一個新的事務。這個新的事務是一個嵌套的事務,一旦關聯的上下文類的SaveChanges()被調用,它就會被提交。

在這種情況下,我們甚至不需要TransactionScope。我們可以簡單地檢查兩個操作的結果,如果它們成功,我們只需調用SaveChanges()方法。

當我們將ADO.NET調用與實體框架混合時,通常需要TransactionScope。在這種情況下使用TransactionScope的訣竅是讓上下文類知道你想用它來處理你自己的事務。由於事務與範圍內的連接對象相關聯,所以我們需要使用與事務範圍關聯的連接的上下文類。此外,我們需要讓上下文類知道它不能擁有連接,因爲它由調用代碼擁有。所以我們可以這樣做:

using (var scope = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    using (var conn = new SqlConnection("...")) 
    { 
     conn.Open(); 

     var sqlCommand = new SqlCommand(); 
     sqlCommand.Connection = conn; 
     sqlCommand.CommandText = 
      @"UPDATE Blogs SET Rating = 5" + 
       " WHERE Name LIKE '%Entity Framework%'"; 
     sqlCommand.ExecuteNonQuery(); 

     using (var context = 
      new BloggingContext(conn, contextOwnsConnection: false)) 
     { 
      var query = context.Posts.Where(p => p.Blog.Rating > 5); 
      foreach (var post in query) 
      { 
       post.Title += "[Cool Blog]"; 
      } 
      context.SaveChanges(); 
     } 
    } 

    scope.Complete(); 
} 

參見:http://msdn.microsoft.com/en-us/data/dn456843.aspx