2011-03-07 42 views
3

我使用實體框架4創建了一個非常簡單的數據庫。我希望能夠在實體上使用事務,但似乎無法保持回滾的更改。我真的只需要一種方法來在實體保存到數據庫之前放棄對實體的臨時更改。如何使用實體框架對象上下文執行事務?

例如,以下代碼使用實體框架對象上下文「MusicContainer」。在TransactionScope中,創建一個Artist實體。交易結束後沒有完成;所以我期望事務被回滾。但是,程序運行起來就好像我從未創建過TransactionScope;在TransactionScope結束之後,線路music.SaveChanges()將對象保存到數據庫。

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
      } 
      // The transaction ended without Complete(); shouldn't the changes be abandoned? 
      music.SaveChanges(); 
     } 
    } 
} 

如果實體框架不使用的TransactionScope,我期待它給來這裏的路上,我怎麼能得到我要找的功能?我有幾種情況,一個函數的調用者在MusicContainer中傳入,並且在我從函數返回之前,我需要將MusicContainer保持在一個乾淨的狀態(即回滾更改,以便它們不會意外地被另一個SaveChanges調用在同一個MusicContainer對象上)。

回答

7

你並不需要一個TransactionScope在所有在這種情況下,SaveChanges()是所有的需要 - 如果你有其他using塊與MusicContainer,這將是一個單獨的事務,不會保存的任何變化您目前的using區塊。 TransactionScope僅適用於跨越多個數據庫上下文的事務。

一般情況下,上下文只能用於由相關操作組成的工作單元,一旦它們完成,請致電SaveChanges()。爲每個單獨的,不相關的工作單元開闢一個新的環境。話雖如此,只需在你的場景中使用這個:

​​
+0

您是否建議我爲每筆交易使用單獨的「使用(MusicContainer music = new MusicContainer())」?我的第一個懷疑是,如果我有幾十個並行發生的話,這將是一個瓶頸 - 我錯了嗎? – 2011-03-07 17:22:57

+2

@notfed我相信開銷很小 - 數據庫連接僅在需要時由EF使用,即調用'SaveChanges()'或執行查詢時,還可以查看此MSDN文章:http://msdn.microsoft.com/ en-us/library/cc853327.aspx – BrokenGlass 2011-03-07 17:42:44

+2

@notfed:您必須爲每個事務使用新的容器。閱讀這裏:http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 – 2011-03-07 18:00:13

2

你有你的SaveChanges在錯誤的地方。

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
      } 
      // The transaction ended without Complete(); the changes are abandoned? 
     } 
    } 
} 

如果交易失敗,您不應該重複使用您的MusicContainer。爲每個Unit of Work

+0

我有SaveChanges在故意的地方。我的觀點是:在我給出的代碼中,爲什麼SaveChanges保存這些更改? – 2011-03-07 17:16:30

+1

您必須在MusicContainer之前聲明TransactionScope。 – edze 2011-03-07 17:24:43

0

實體框架的新人們應該能夠使用TransactionScope的。如果需要僅通過此方法回滾所允許的更改,則需要啓動新的TransactionScope。

using (MusicContainer music = new MusicContainer()) 
    { 
    using (TransactionScope transaction = new TransactionScope(TransactionScopeOptions.RequiresNew)) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
       scope.Complete(); 
      } 
    } 
+0

好吧,如果我從一個調用者函數傳遞一個MusicContainer,我沒有選擇在TransactionScope中創建MusicContainer。 – 2011-03-07 17:18:42

+0

然後你不需要在你的方法中調用SaveChanges。讓頂層函數調用SaveChanges – Amitabh 2011-03-07 17:22:17

+0

但是,我需要_abandon_對對象上下文所做的更改,我不希望調用方保存這些更改。 – 2011-03-07 17:24:37