2

這是使用事務範圍的正確方法:使用的TransactionScope多次

我有代表的東西一部分的對象:

public class ThingPart 
{ 
    private DbProviderFactory connectionFactory; 

    public void SavePart() 
    { 
     using (TransactionScope ts = new TransactionScope() 
     { 
      ///save the bits I want to be done in a single transaction 
      SavePartA(); 
      SavePartB(); 
      ts.Complete(); 
     } 
    } 

    private void SavePartA() 
    { 
     using (Connection con = connectionFactory.CreateConnection() 
     { 
      con.Open(); 
      Command command = con.CreateCommand(); 
      ... 
      command.ExecuteNonQuery();    
     } 
    } 

    private void SavePartB() 
    { 
     using (Connection con = connectionFactory.CreateConnection() 
     { 
      con.Open(); 
      Command command = con.CreateCommand(); 
      ... 
      command.ExecuteNonQuery();    
     } 
    } 
} 

而且一些東西,代表事情:

public class Thing 
{ 
    private DbProviderFactory connectionFactory; 

    public void SaveThing() 
    { 
     using (TransactionScope ts = new TransactionScope() 
     { 
      ///save the bits I want to be done in a single transaction 
      SaveHeader(); 
      foreach (ThingPart part in parts) 
      { 
       part.SavePart(); 
      } 
      ts.Complete();  
     } 
    } 

    private void SaveHeader() 
    { 
     using (Connection con = connectionFactory.CreateConnection() 
     { 
      con.Open(); 
      Command command = con.CreateCommand(); 
      ... 
      command.ExecuteNonQuery();    
     } 
    } 
} 

我也有東西管理很多東西

public class ThingManager 
{  
    public void SaveThings 
    {   
     using (TransactionScope ts = new TransactionScope) 
     {    
      foreach (Thing thing in things) 
      { 
       thing.SaveThing(); 
      }    
     }   
    }  
} 

其我的理解是:

  • 的連接不會是新的,將被每次從池中重複使用(假設DbProvider支持連接池,並已啓用)
  • 該交易將使得如果我只是打電話給ThingPart.SavePart(從任何其他課程的背景之外),那麼A部分和B部分都將被保存,或者都不會。
  • 如果我叫Thing.Save(從其它類的上下文之外),那麼頁眉和所有的零部件將全部保存或非會,即一切都將在同一個事務
  • 發生,如果我叫ThingManager.SaveThings那麼所有我的東西將會被保存或者不會被保存,也就是說,一切都會在同一次交易中發生。
  • 如果我改變DbProviderFactory實現即用,它不應該有所作爲

是我的假設是否正確?

忽略任何關於對象結構或持久化的責任,這是一個幫助我理解我應該如何做事的例子。部分原因是因爲它似乎不工作,當我嘗試用SqlLite作爲數據庫提供程序工廠替換Oracle時,我想知道應該在哪裏花時間調查。

回答

3

回答你的子彈(並且我認爲微軟SQL Server 2005或更高版本):

  1. 連接不會被新的,從池中

    • 這取決於重用 - 例如如果所有連接都是相同的數據庫,憑證相同,並且SQL能夠使用Lightweight事務管理器(SQL 2005及更高版本),則SAME連接將在您的聚合事務中的後續步驟中重用。 (但SQL連接池仍然有效,如果這是你問的東西?)
  2. Atomic SavePart - 是的,這將工作如預期的酸。
  3. 是嵌套具有相同範圍的TransactionScopes也將是原子。交易只會在最外面的TS完成時提交。
  4. 是的,也是原子,但請注意,您將升級SQL鎖。如果單獨提交每個Thing(及其ThingParts)是有意義的,則從SQL併發性角度來看,這將是更可取的。
  5. Provider需要兼容TransactionScope資源管理器(也可能是DTC兼容)。例如不要將你的數據庫移動到Rocket U2,並期望TransactionScopes工作。

只有一個問題 - new TransactionScope() defaults to isolation level READ_SERIALIZABLE - 對於大多數情況,這通常是悲觀的 - READ COMMITTED通常更適用。

+0

相關:http://stackoverflow.com/a/22512547/314291 – StuartLC

相關問題