挖掘使用ADO.NET分布式事務(wù)登記
ADO.NET經(jīng)過長時間的發(fā)展,很多用戶都很了解ADO.NET分布式事務(wù)了,這里我發(fā)表一下個人理解,和大家討論討論。事務(wù)是一組相關(guān)的任務(wù),作為獨(dú)立于其他任務(wù)的獨(dú)立單元成功(提交)或失敗(中止)。分布式事務(wù)是影響多個資源的事務(wù)。要提交分布式事務(wù),所有參與者都必須保證對數(shù)據(jù)的任何更改是永久的。不論系統(tǒng)崩潰或是發(fā)生其他無法預(yù)料的事件,更改都必須是持久的。即使只有一個參與者無法保證這一點(diǎn),整個事務(wù)也將失敗,在事務(wù)范圍內(nèi)對數(shù)據(jù)的任何更改均將回滾。如果 DataReader 在事務(wù)處于活動狀態(tài)時啟動,此時若嘗試提交或回滾事務(wù),將會引發(fā)異常。
使用 System.Transactions
在 .NET Framework 中,分布式事務(wù)通過 System.Transactions 命名空間中的 API 進(jìn)行管理。如果涉及多個永久資源管理器,System.Transactions API 會將分布式事務(wù)處理委托給事務(wù)監(jiān)視器,例如 Microsoft 分布式事務(wù)協(xié)調(diào)程序 (MS DTC)。有關(guān)更多信息,請參見事務(wù)基礎(chǔ)知識。
ADO.NET 2.0 引入了對使用 EnlistTransaction 方法在分布式事務(wù)中進(jìn)行登記的支持,該方法會登記 Transaction 實(shí)例中的連接。在以前版本的 ADO.NET 中,分布式事務(wù)中的顯式登記使用連接的 EnlistDistributedTransaction 方法執(zhí)行,以登記 ITransaction 實(shí)例中的連接,為了向后兼容,也支持該方法。有關(guān)企業(yè)服務(wù)事務(wù)的更多信息,請參見 與企業(yè)服務(wù)和 COM+ 事務(wù)的互操作性。
在對 SQL Server 2005 數(shù)據(jù)庫使用 SQL Server .NET Framework 提供程序提供的 System.Transactions 事務(wù)時,將自動使用輕型 Transaction。該事務(wù)可以根據(jù)需要提升為完全分布式事務(wù)。有關(guān)更多信息,請參見SQL Server 的 System.Transactions 集成 (ADO.NET)。默認(rèn)情況下,Oracle 數(shù)據(jù)庫可以同時參與的分布式事務(wù)的最大數(shù)目設(shè)置為 10。第 10 個事務(wù)之后,連接到 Oracle 數(shù)據(jù)庫時將會引發(fā)異常。Oracle 不支持分布式事務(wù)內(nèi)的 DDL。
自動在ADO.NET分布式事務(wù)中登記
自動登記是將 ADO.NET 連接與 System.Transactions 集成的默認(rèn)(和首選)方法。如果連接對象確定事務(wù)處于活動狀態(tài),用 System.Transaction 術(shù)語來說是指 Transaction.Current 不為 Null,則連接對象會自動在現(xiàn)有分布式事務(wù)中登記。自動事務(wù)登記在連接打開時進(jìn)行。之后,即使在事務(wù)范圍內(nèi)執(zhí)行命令,也不會進(jìn)行自動事務(wù)登記??梢栽诂F(xiàn)有事務(wù)中禁用自動登記,方法是將 Enlist=false 指定為 ConnectionString 的連接字符串參數(shù),或?qū)?OLE DB Services=-7 指定為 ConnectionString 的連接字符串參數(shù)。有關(guān) Oracle 和 ODBC 連接字符串參數(shù)的更多信息,請參見 ConnectionString 和 ConnectionString。
手動在ADO.NET分布式事務(wù)中登記
如果禁用了自動登記或者您需要登記在連接打開后啟動的事務(wù),則可以使用所用提供程序的 DbConnection 對象的 EnlistTransaction 方法,在現(xiàn)有分布式事務(wù)中登記。在現(xiàn)有分布式事務(wù)中登記可以確保當(dāng)提交或回滾了事務(wù)時,也提交或回滾對數(shù)據(jù)源所做作的代碼修改。
在分布式事務(wù)中登記尤其適用于為業(yè)務(wù)對象建立池連接。如果業(yè)務(wù)對象使用打開的連接建立池連接,自動事務(wù)登記只有在該連接打開時才會進(jìn)行。如果使用池中的業(yè)務(wù)對象執(zhí)行多個事務(wù),則該對象的打開連接不自動登記在新啟動的事務(wù)中。在這種情況下,可以對該連接禁用自動事務(wù)登記,并使用 EnlistTransaction 在事務(wù)中登記連接。
EnlistTransaction 使用單個 Transaction 類型的參數(shù),該參數(shù)引用現(xiàn)有的事務(wù)。在調(diào)用連接的 EnlistTransaction 方法之后,所有使用該連接在數(shù)據(jù)源上進(jìn)行的修改均將加入事務(wù)中。傳遞空值將取消該連接在當(dāng)前分布式事務(wù)登記中的登記。注意,在調(diào)用 EnlistTransaction 之前連接必須打開。在某個事務(wù)中顯式登記了連接之后,在該事務(wù)完成之前,連接將無法取消登記或在另一個事務(wù)中登記。
#T#如果連接已使用連接的 BeginTransaction 方法開始了某個事務(wù),EnlistTransaction 將引發(fā)異常。但是,如果事務(wù)是在數(shù)據(jù)源上開始的本地事務(wù)(例如使用 SqlCommand 顯式執(zhí)行 BEGIN TRANSACTION 語句),EnlistTransaction 將回滾該本地事務(wù)并根據(jù)請求在現(xiàn)有分布式事務(wù)中登記。您不會接收本地事務(wù)已回滾的通知,必須管理任何未使用 BeginTransaction 開始的本地事務(wù)。如果您在 SQL Server 2005 中使用用于 SQL Server 的 .NET Framework 數(shù)據(jù)提供程序 (SqlClient),那么在嘗試登記時將會引發(fā)異常。所有其他情況將無法發(fā)現(xiàn)。