在.net 2.0 中执行分布式事务:隐式事务篇(SQL Server 与 Oracle)
生活随笔
收集整理的這篇文章主要介紹了
在.net 2.0 中执行分布式事务:隐式事务篇(SQL Server 与 Oracle)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
項目涉及到多個數據庫的查詢更新操作,也就必然需要分布式事務的支持,查了MSDN知道 .net 2.0 中利用新增的 System.Transactions 命名空間可以簡單的實現分布式事務:
System.Transactions?基礎結構通過支持在?SQL?Server、ADO.NET、MSMQ?和?Microsoft?分布式事務協調器?(MSDTC)?中啟動的事務,使事務編程在整個平臺上變得簡單和高效。它提供基于?Transaction?類的顯式編程模型,還提供使用?TransactionScope?類的隱式編程模型,在這種模型中事務是由基礎結構自動管理的。強烈建議使用更為方便的隱式模型進行開發。 具體參考:http://msdn2.microsoft.com/zh-cn/library/system.transactions(VS.80).aspx 以及相關的連接都提供了非常詳細的信息參考MSDN的Demo做了SQL Server 2000 的 使用事務范圍實現隱式事務測試,事務可以正常提交以及回滾:
private?void?Test1()
????{
????????//?使用事務范圍實現隱式事務
????????//?ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_fxtransactions/html/1ddba95e-7587-48b2-8838-708c275e7199.htm
????????using?(TransactionScope?ts?=?new?TransactionScope())?{
????????????//Create?and?open?the?SQL?connection.??The?work?done?on?this?connection?will?be?a?part?of?the?transaction?created?by?the?TransactionScope
????????????SqlConnection?myConnection?=?new?SqlConnection("server=(local);Integrated?Security=SSPI;database=northwind");
????????????SqlCommand?myCommand?=?new?SqlCommand();
????????????myConnection.Open();
????????????myCommand.Connection?=?myConnection;
????????????if?(!chkGenError.Checked)?{
????????????????//Restore?database?to?near?it's?original?condition?so?sample?will?work?correctly.
????????????????myCommand.CommandText?=?"DELETE?FROM?Region?WHERE?(RegionID?=?100)?OR?(RegionID?=?101)";
????????????????myCommand.ExecuteNonQuery();
????????????}
????????????//Insert?the?first?record.
????????????myCommand.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(100,?'MidWestern')";
????????????myCommand.ExecuteNonQuery();
????????????//Insert?the?second?record.
????????????myCommand.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(101,?'MidEastern')";
????????????myCommand.ExecuteNonQuery();
????????????myConnection.Close();
????????????if?(chkCommit.Checked)?{
????????????????ts.Complete();
????????????}
????????????/**/////Call?complete?on?the?TransactionScope?or?not?based?on?input
????????????//ConsoleKeyInfo?c;
????????????//while?(true)?{
????????????//????Console.Write("Complete?the?transaction?scope??[Y|N]?");
????????????//????c?=?Console.ReadKey();
????????????//????Console.WriteLine();
????????????//????if?((c.KeyChar?==?'Y')?||?(c.KeyChar?==?'y'))?{
????????????//????????//?Commit?the?transaction
????????????//????????ts.Complete();
????????????//????????break;
????????????//????}
????????????//????else?if?((c.KeyChar?==?'N')?||?(c.KeyChar?==?'n'))?{
????????????//????????break;
????????????//????}
????????????//}
????????}
????}
????private?void?Test2()
????{
????????string?connectString1?=?"server=(local);Integrated?Security=SSPI;database=northwind";
????????string?connectString2?=?"server=(local);Integrated?Security=SSPI;database=pubs";
????????string?dt?=?DateTime.Now.ToString();
????????using?(TransactionScope?transScope?=?new?TransactionScope())?{
????????????using?(SqlConnection?connection1?=?new
???????????????SqlConnection(connectString1))?{
????????????????//?Opening?connection1?automatically?enlists?it?in?the?
????????????????//?TransactionScope?as?a?lightweight?transaction.
????????????????connection1.Open();
????????????????//?Do?work?in?the?first?connection.
????????????????SqlCommand?command1?=?new?SqlCommand();????????????????
????????????????command1.Connection?=?connection1;
????????????????//Restore?database?to?near?it's?original?condition?so?sample?will?work?correctly.
????????????????command1.CommandText?=?"DELETE?FROM?Region?WHERE?(RegionID?=?100)?OR?(RegionID?=?101)";
????????????????command1.ExecuteNonQuery();
????????????????//Insert?the?first?record.
????????????????command1.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(100,?'MidWestern')";
????????????????command1.ExecuteNonQuery();
????????????????//Insert?the?second?record.
????????????????command1.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(101,?'MidEastern')";
????????????????command1.ExecuteNonQuery();
????????????????//?Assumes?conditional?logic?in?place?where?the?second
????????????????//?connection?will?only?be?opened?as?needed.
????????????????using?(SqlConnection?connection2?=?new
????????????????????SqlConnection(connectString2))?{
????????????????????//?Open?the?second?connection,?which?enlists?the?
????????????????????//?second?connection?and?promotes?the?transaction?to
????????????????????//?a?full?distributed?transaction.?
????????????????????connection2.Open();
???????????????????
????????????????????//?Do?work?in?the?second?connection.
????????????????????SqlCommand?command2?=?new?SqlCommand();????????????????????
????????????????????command2.Connection?=?connection2;
????????????????????if?(!chkGenError.Checked)?{
????????????????????????//Restore?database?to?near?it's?original?condition?so?sample?will?work?correctly.
????????????????????????command2.CommandText?=?"DELETE?FROM?stores?WHERE?(stor_id?=?'9797')?OR?(stor_id?=?'9798')";
????????????????????????command2.ExecuteNonQuery();
????????????????????}
????????????????????//Insert?the?first?record.
????????????????????command2.CommandText?=?"Insert?into?stores?(stor_id,?stor_name)?VALUES?('9797',?'ebay')";
????????????????????command2.ExecuteNonQuery();
????????????????????//Insert?the?second?record.
????????????????????command2.CommandText?=?"Insert?into?stores?(stor_id,?stor_name)?VALUES?('9798',?'amazon')";
????????????????????command2.ExecuteNonQuery();????????????????????
????????????????}
????????????}
????????????//??The?Complete?method?commits?the?transaction.
????????????if?(chkCommit.Checked)?{
????????????????transScope.Complete();
????????????}
????????}
????}
????private?void?Test3()
????{
????????string?connectString1?=?"server=(local);Integrated?Security=SSPI;database=northwind";
????????string?connectString2?=?"server=(local);Integrated?Security=SSPI;database=pubs";
????????string?dt?=?DateTime.Now.ToString();
????????using?(TransactionScope?transScope?=?new?TransactionScope())?{
????????????using?(SqlConnection?connection1?=?new
???????????????SqlConnection(connectString1))?{
????????????????//?Opening?connection1?automatically?enlists?it?in?the?
????????????????//?TransactionScope?as?a?lightweight?transaction.
????????????????connection1.Open();
????????????????//?Do?work?in?the?first?connection.
????????????????SqlCommand?command1?=?new?SqlCommand();
????????????????command1.Connection?=?connection1;
????????????????//Restore?database?to?near?it's?original?condition?so?sample?will?work?correctly.
????????????????command1.CommandText?=?"DELETE?FROM?Region?WHERE?(RegionID?=?100)?OR?(RegionID?=?101)";
????????????????command1.ExecuteNonQuery();
????????????????//Insert?the?first?record.
????????????????command1.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(100,?'MidWestern')";
????????????????command1.ExecuteNonQuery();
????????????????//Insert?the?second?record.
????????????????command1.CommandText?=?"Insert?into?Region?(RegionID,?RegionDescription)?VALUES?(101,?'MidEastern')";
????????????????command1.ExecuteNonQuery();
????????????}
????????????//?Assumes?conditional?logic?in?place?where?the?second
????????????//?connection?will?only?be?opened?as?needed.
????????????using?(SqlConnection?connection2?=?new
????????????????SqlConnection(connectString2))?{
????????????????//?Open?the?second?connection,?which?enlists?the?
????????????????//?second?connection?and?promotes?the?transaction?to
????????????????//?a?full?distributed?transaction.?
????????????????connection2.Open();
????????????????//?Do?work?in?the?second?connection.
????????????????SqlCommand?command2?=?new?SqlCommand();
????????????????command2.Connection?=?connection2;
????????????????if?(!chkGenError.Checked)?{
????????????????????//Restore?database?to?near?it's?original?condition?so?sample?will?work?correctly.
????????????????????command2.CommandText?=?"DELETE?FROM?stores?WHERE?(stor_id?=?'9797')?OR?(stor_id?=?'9798')";
????????????????????command2.ExecuteNonQuery();
????????????????}
????????????????//Insert?the?first?record.
????????????????command2.CommandText?=?"Insert?into?stores?(stor_id,?stor_name)?VALUES?('9797',?'ebay')";
????????????????command2.ExecuteNonQuery();
????????????????//Insert?the?second?record.
????????????????command2.CommandText?=?"Insert?into?stores?(stor_id,?stor_name)?VALUES?('9798',?'amazon')";
????????????????command2.ExecuteNonQuery();
????????????}
????????????//??The?Complete?method?commits?the?transaction.
????????????if?(chkCommit.Checked)?{
????????????????transScope.Complete();
????????????}
????????}
????}????
?
測試的時候需要在 Sql Server 服務管理器中開啟 MSDTC,我是再 SQL 2k上做的測試,2k5上應該得到更好的支持。
方法 Test1()?是單數據庫的事務,只是為了測試;
?Test2()和Test3() 沒有實質區別,都是自動注冊事務。
完整代碼下載:/Files/Jinglecat/DTCSQL.rar
同時我也嘗試了一個Oracle版本,Oracle 10g 2,其中數據庫orcl 是默認的啟動數據庫,而數據庫nhrs是我自己建的一個數據庫,測試通過,代碼跟SQL沒有兩樣,之前網上查到有網友說OracleClient還不支持 MSDTC,查了很多資料,確實在 ado.net 1.x 有問題,現在可以確信 ado.net 2.0 已經可以支持。
完整代碼下載:/Files/Jinglecat/DTCORA.rar
現在銀杏事務已經可以滿數項目需求了,有時間再多更多的研究了^_^
轉載于:https://www.cnblogs.com/Jinglecat/archive/2007/04/07/704297.html
總結
以上是生活随笔為你收集整理的在.net 2.0 中执行分布式事务:隐式事务篇(SQL Server 与 Oracle)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据结构与算法】【算法思想】【MySQ
- 下一篇: mssql数据库置疑修复