2011-11-26 86 views
8

您好我正在嘗試與實體框架一起使用交易。網上有很多關於實現交易的不同方式的信息,我必須說我在正確的方式上有點困惑。我有一個包含Employee和Company兩個表的示例數據庫。 Employee表具有引用公司Id的外鍵。考慮到我想實現一個事務,我插入一條記錄到公司表,然後記錄到僱員表,我想這樣做,只有在記錄插入都成功時我有以下代碼。瞭解實體框架中的交易

public void addCompanyToDatabase() 
    { 
     using (var context = new myTestEntities()) 
     { 
      context.Connection.Open(); //added this as was getting the underlying 
      //provider failed to open 
      using (TransactionScope scope = new TransactionScope()) 
      { 
       try 
       { 
        Company c = new Company(); 
        c.Name = "xyz"; 
        context.Companies.AddObject(c); 
        context.SaveChanges(); 

        //int a = 0; 
        //int b = 5/a; 

        Employee e = new Employee(); 
        e.Age = 15; 
        e.Name = "James"; 
        e.CompanyId = c.Id; 
        context.Employees.AddObject(e); 
        context.SaveChanges(); 

        scope.Complete(); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("Exception Occurred"); 
       } 
      } 
     } 
    } 

我想知道這是否是實施交易的正確方法。如果是,那麼SaveChanges(false)scope.AcceptAllChanges()函數的用途是什麼。任何信息都有幫助。

回答

14

在你的情況下,你不需要管理任何連接或事務:實體框架將爲你做到這一點。當您不提供打開連接(但帶有連接字符串)的EF時,它將打開一個連接,並在撥打context.SaveChanges()期間開始一個事務。在該呼叫期間某些事件失敗時,交易將被回滾。

換句話說,你的方法可以簡單地是這樣的:

public void addCompanyToDatabase() 
{ 
    using (var context = new myTestEntities()) 
    { 
     Company c = new Company(); 
     c.Name = "xyz"; 
     context.Companies.AddObject(c); 

     Employee e = new Employee(); 
     e.Age = 15; 
     e.Name = "James"; 
     e.CompanyId = c.Id; 
     context.Employees.AddObject(e); 

     // Only call SaveChanges last. 
     context.SaveChanges(); 
    } 
} 
+0

這對我的例子來說是有道理的。你能舉個例子說明我需要交易嗎?如果我上面提到的代碼是執行交易的方式?我猜想用兩種不同的上下文更新記錄是一種情況。 – nighthawk457

+1

我遇到過的最常見的情況是您需要一個事務,那就是您需要多次調用'SaveChanges'時。當需要新對象的(數據庫生成的)id時,或者當您需要強制ORM以特定順序執行操作時(例如,LINQ to SQL傾向於在插入後重新排序刪除操作,但這可能會觸發數據庫約束例外)。 – Steven

+3

在所有情況下,仍然不需要使用'TransactionScope'。如果您需要'TransactionScope'因爲您需要對多個數據庫進行原子操作,那麼您的系統中可能存在設計缺陷。我使用'TransactionScope'完全用於我的自動化集成測試。只需在'TransactionScope'中說出調用代碼,就可以確保所有(數據庫)更改在測試結束時回滾,而無需爲此更改任何代碼。 – Steven

0

1 - 這服務(我認爲交易服務)必須在客戶端運行支持的TransactionScope

2 - 當您的應用程序中有兩個或多個數據庫並且希望所有數據庫更新事務性(例如更改您的上下文的連接字符串)時,請使用它。

3 - 當你有一個數據庫時最好使用SaveChanges()來實現事務的內部實現。