在本人的 “ .NET简谈事务本质论”一文中我们从整体上了解了事务模型,在我们脑子里能有一个全局的事务处理结构,消除对数据库事务的依赖理解,重新认识事务编程模型。
- insert into test values('222') --我们在表test中插入一条记录
- go
- begin transaction tr
- begin try
- begin
- insert into test2 values('111')
- insert into test values('222') --该行插入会导致主键冲突,也就是我们要的效果
- end
- commit transaction tr
- end try
- begin catch
- print '事务执行错误!'
- print error_number()
- rollback transaction tr
- end catch
例2:
- public class Test
- {
- SqlConnection conn = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- public void Add()
- {
- conn.Open();
- SqlCommand command = new SqlCommand("insert into test2 values(111)", conn);
- try
- {
- command.Transaction = conn.BeginTransaction();
- command.ExecuteNonQuery();
- command.CommandText = "insert into test values(222)";
- command.ExecuteNonQuery();
- command.Transaction.Commit();
- }
- catch (Exception err)
- {
- Console.WriteLine(err);
- command.Transaction.Rollback();
- }
- }
- }
- public class DisplayTransactioninfo
- {
- public static void Display(System.Transactions.Transaction tr)
- {
- if (tr != null)
- {
- Console.WriteLine("Createtime:" + tr.TransactionInformation.CreationTime);
- Console.WriteLine("Status:" + tr.TransactionInformation.Status);
- Console.WriteLine("Local ID:" + tr.TransactionInformation.LocalIdentifier);
- Console.WriteLine("Distributed ID:" + tr.TransactionInformation.DistributedIdentifier);
- Console.WriteLine();
- }
- }
- public class Test3
- {
- SqlConnection conn;
- CommittableTransaction committran = new CommittableTransaction();
- public Test3()
- {
- conn = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- DisplayTransactioninfo.Display(committran);
- }
- public void Add3()
- {
- conn.Open();
- conn.EnlistTransaction(committran);//需要将本次的连接操作视为事务性的
- SqlCommand command = new SqlCommand();
- try
- {
- command.Connection = conn;
- command.CommandText = "insert into test2 values(111)";
- command.ExecuteNonQuery();
- command.CommandText = "insert into test values(222)";
- command.ExecuteNonQuery();
- committran.Commit();
- }
- catch (Exception err) { committran.Rollback(); //出现出错执行回滚操作}
- }
- }
- [System.Runtime.InteropServices.ComVisible(true)]
- //COM+是在COM的基础上发展起来的,需要将.NET程序集中的类型公开为COM组件。
- [System.EnterpriseServices.Transaction(TransactionOption.Required)]//始终需要事务处理域
- public class Test2 : ServicedComponent
- {
- public Test2() { }
- SqlConnection conn = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- [AutoComplete(true)]
- //如果在方法的执行体类没有出现错误,那么将自动设置事务处理的结果
- public void Add2()
- {
- conn.Open();
- SqlCommand command = new SqlCommand();
- try
- {
- command.Connection = conn;
- command.CommandText = "insert into test2 values(111)";
- command.ExecuteNonQuery();
- command.CommandText = "insert into test values(222)";
- command.ExecuteNonQuery();
- }
- catch { System.EnterpriseServices.ContextUtil.SetAbort(); }
- }
- }
- public class Test6
- {
- CommittableTransaction commit = new CommittableTransaction();
- SqlConnection conn1 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- public Test6()
- {
- conn1.Open();
- conn1.EnlistTransaction(commit);
- }
- public void Add6()
- {
- try
- {
- DisplayTransactioninfo.Display(commit);
- SqlCommand command = new SqlCommand("insert into test2 values(111)", conn1);
- command.ExecuteNonQuery();
- Thread thread = new Thread(Test6.CommitThread);
- thread.Start(commit.DependentClone(DependentCloneOption.BlockCommitUntilComplete));
- commit.Commit();
- }
- catch (Exception err) { commit.Rollback(); }
- }
- public static void CommitThread(object co)
- {
- DependentTransaction commit = co as DependentTransaction;
- SqlConnection conn2 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- conn2.Open();
- conn2.EnlistTransaction(commit as DependentTransaction);
- DisplayTransactioninfo.Display(commit);
- SqlCommand command = new SqlCommand("insert into test values(111)", conn2);
- try
- {
- command.ExecuteNonQuery();
- commit.Complete();
- }
- catch (Exception err) { Console.WriteLine(err); commit.Rollback(); }
- }
- }
- public class Test4
- {
- SqlConnection conn1 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- SqlConnection conn2 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- CommittableTransaction committran = new CommittableTransaction();
- public Test4()
- {
- DisplayTransactioninfo.Display(committran);
- conn1.Open();
- conn1.EnlistTransaction(committran);
- conn2.Open();
- conn2.EnlistTransaction(committran);
- DisplayTransactioninfo.Display(committran);
- }
- public void Add4()
- {
- try
- {
- SqlCommand command1 = new SqlCommand("insert into test2 values(111)", conn1);
- command1.ExecuteNonQuery();
- SqlCommand command2 = new SqlCommand("insert into test values(222)", conn2);
- command2.ExecuteNonQuery();
- }
- catch (Exception err) { Console.WriteLine(err); committran.Rollback(); }
- }
- }
- //服务契约(ServiceContract):
- [ServiceContract(SessionMode = SessionMode.Required)]
- public interface IDistributedTransaction
- {
- [TransactionFlow(TransactionFlowOption.Allowed)]
- [OperationContract]
- void Add();
- }
- //服务类1:
- public class DistributedTransactionService1 : IDistributedTransaction
- {
- SqlConnection conn1 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- #region IDistributedTransaction
- [OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
- public void Add()
- {
- conn1.Open();
- SqlCommand command = new SqlCommand("insert into test2 values(111)", conn1);
- command.ExecuteNonQuery();
- DataBaseOperation.DisplayTransactioninfo.Display(System.Transactions.Transaction.Current);
- }
- #endregion
- }
- //服务类2:
- public class DistributedTransactionService2 : IDistributedTransaction
- {
- SqlConnection conn2 = new SqlConnection("data source=.;Initial Catalog=DataMedicine;Integrated Security=SSPI");
- #region IDistributedTransaction
- [OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
- public void Add()
- {
- conn2.Open();
- SqlCommand command = new SqlCommand("insert into test values(222)", conn2);
- try
- {
- DataBaseOperation.DisplayTransactioninfo.Display(System.Transactions.Transaction.Current);
- command.ExecuteNonQuery();
- }
- catch (Exception err) { throw err; }
- }
服务配置:
- <service name="ServerConsole.Transaction.DistributedTransactionService1" behaviorConfiguration="metadatabehaviors">
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:8027"/>
- <add baseAddress="net.tcp://localhost:8028"/>
- </baseAddresses>
- </host>
- <endpoint address="DistributedTransactionService1" binding="netTcpBinding" bindingConfiguration="tranbinding"
- contract="ServerConsole.Transaction.IDistributedTransaction"></endpoint>
- </service>
- <service name="ServerConsole.Transaction.DistributedTransactionService2" behaviorConfiguration="metadatabehaviors">
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:8029"/>
- <add baseAddress="net.tcp://localhost:8030"/>
- </baseAddresses>
- </host>
- <endpoint address="DistributedTransactionService2" binding="netTcpBinding" bindingConfiguration="tranbinding"
- contract="ServerConsole.Transaction.IDistributedTransaction"></endpoint>
- </service>
Binding配置:
- <bindings>
- <netTcpBinding>
- <binding name="tranbinding" transactionFlow="true" transactionProtocol="WSAtomicTransactionOctober2004">
- <reliableSession enabled="true" ordered="true"/>
- </binding>
- </netTcpBinding>
- </bindings>
我们需要打开Binding的事务流传递。
客户端代码:
- 客户端:
- DistributedTransactionClient.DistributedTransactionClient tranclient = new DistributedTransactionClient.DistributedTransactionClient();
- DistributedTransaction2Client.DistributedTransactionClient tranclient2 = new DistributedTransaction2Client.DistributedTransactionClient();
- using (TransactionScope transcope = new TransactionScope())
- {
- try
- {
- Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(Current_TransactionCompleted);
- tranclient.Add();
- tranclient2.Add();
- transcope.Complete();
- }
- catch (Exception err) { Transaction.Current.Rollback(); }
- }
- static void Current_TransactionCompleted(object sender, TransactionEventArgs e)
- {
- if (e.Transaction.TransactionInformation.Status ==
- System.Transactions.TransactionStatus.Committed)
- Console.WriteLine(e.Transaction.TransactionInformation.DistributedIdentifier);
- }