2010-01-04 94 views
1

我有一個使用了大量SqlTranaction調用現有的應用程序。該應用程序的構建方式,我們得到了一堆代碼,看起來有點像這樣(爲簡便起見錯誤處理等去掉):我應該如何將SqlTransaction遺留代碼與TranactionScope集成?

Using transaction As SqlTransaction = Database.CreateSqlTransaction() 
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert(transaction) 
    Else 
     Me.FitnessSession.Update(transaction) 
    End If 
    SaveTestScores(transaction) 

    Database.CommitTransaction(transaction) 'This essentially just calls transaction.Commit() 

End Using 

我們在開溝出手卷DAL和移動到LINQ的過程到SQL,但這將是增量式的,因爲我們沒有預算來簡單地丟棄所有我們的遺留代碼。因此,我們將在我們需要使用我們的舊代碼和Linq到SQL代碼的所有領域都處於同一事務中。我相信這可以這樣做:

Using scope As New TransactionScope() 
Using transaction As SqlTransaction = Database.CreateSqlTransaction() 
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert(transaction) 
    Else 
     Me.FitnessSession.Update(transaction) 
    End If 
    SaveTestScores(transaction) 

    Database.CommitTransaction(transaction) 

End Using 
End Using 

什麼我就被其承諾稱不清楚,我必須打電話scope.Complete()Database.CommitTransaction(transaction)?或者還有其他一些選項將兩段代碼鏈接在一起?

跟進質詢,
感謝@編程英雄那是真正有用的,什麼我現在不能確定的是,我的時候應該關閉SQL連接?該DAL方法中的代碼使一個檢查,看是否已經通過了一項交易,如果有,那麼它使用對事務的連接並沒有關閉連接,一旦完成後,如果沒有交易過那麼新連接打開並關閉操作。如果我關閉了TransactionScope中的SqlConnection,這是否會導致環境事務出現問題?我問,因爲如果關閉具有SqlTransaction對象的SqlConnection,事務將回滾。

回答

2

命名空間System.Transactions的用途是允許您在整個應用程序中控制來自單個模型的事務。使用System.Transactions提供的交易模式時,應避免使用任何明確的交易,如SqlTransaction;在明確的交易中混合會使您的生活變得相當困難,因爲您必須手動管理這兩種模型。

對你的好消息:當您使用ADO.NET組件您獲得環境事務的內置支持。這意味着你可以刪除所有引用SqlTransaction和傳遞交易的情況下物體周圍,爲System.Transactions模型會照顧一切的爲您服務。

的環境事務模型可以作爲一個包裝,並協調其他各種具體事務。 ADO.NET組件知道要查找環境事務並在內部設置自己的特定事務(如SqlTransaction)。該System.Transactions組件預警所有的士兵交易的「全局」事務TransactionScope塊管理的狀態。

如果您的代碼在TransactionScope區塊內執行,則會有一個環境事務可供事務感知組件參與。對於您的數據訪問代碼,所有交互都將發生在同一事務中,而不管是否它們是您自己的DAL或Linq to SQL組件的一部分。所有你需要知道的是,只要有人在場,他們就會參加環境交易。

要成功完成TransactionScope塊,只需在工作結束時在本地實例上調用TransactionScope.Complete()即可。爲每一個你在其中工作的塊做這件事,當最頂級塊完成時,物理事務將落實。

沒有必要調用任何其他交易特定的代碼,因爲他們應該都(幕後)與您的System.Transaction協調。

有了這一切記住,你的代碼可以是這樣的:

Using scope As New TransactionScope() 

    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then 
     Me.FitnessSession.Insert() 
    Else 
     Me.FitnessSession.Update() 
    End If 

    SaveTestScores() 

    scope.Complete() 

End Using 

特定數據庫事務的所有引用都消失了。所有操作都將在TransactionScope提供的環境交易中發生。在此塊中,您還可以使用SqlCommand直接調用,或者使用Linq-to-SQL對象而不指定任何顯式事務,並且它們將參與環境事務。

+2

我同意。一個警告 - 'TransactionScope'將升級到一個分佈式事務(這是一個用於部署的PITA),除非所有數據訪問代碼共享一個打開的連接對象。 – 2010-01-04 17:45:27