CommittableTransaction和TransactionScope
创建可提交事务
下面的示例创建一个新的 CommittableTransaction 并提交它。
//Create a committable transaction tx = new CommittableTransaction(); SqlConnection myConnection = new SqlConnection("server=(local)\\SQLExpress;Integrated Security=SSPI;database=northwind"); SqlCommand myCommand = new SqlCommand(); //Open the SQL connection myConnection.Open(); //Give the transaction to SQL to enlist with myConnection.EnlistTransaction(tx); myCommand.Connection = myConnection; // 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(); // Commit or rollback the transaction while (true) { Console.Write("Commit or Rollback? [C|R] "); ConsoleKeyInfo c = Console.ReadKey(); Console.WriteLine(); if ((c.KeyChar == 'C') || (c.KeyChar == 'c')) { tx.Commit(); break; } else if ((c.KeyChar == 'R') || (c.KeyChar == 'r')) { tx.Rollback(); break; } } myConnection.Close(); tx = null;
异步提交
CommittableTransaction 类还提供用于异步提交事务的机制。事务提交可能会占用相当长的时间,因为它可能涉及多个数据库访问并可能有网络滞后时间。如果您想要在具有高吞吐量的应用程序中避免死锁,则可以使用异步提交尽可能快地完成事务工作,并且将提交操作作为后台任务执行。CommittableTransaction 类的 BeginCommit 和 EndCommit 方法支持您这样做。
您可以调用 BeginCommit 以将延迟的提交分配给来自线程池的线程。您还可以调用 EndCommit,确定是否已实际提交事务。如果事务出于任何原因未能提交,则 EndCommit 引发事务异常。如果在调用 EndCommit 时尚未提交该事务,则在提交或中止该事务前阻塞调用方。
进行异步提交的最简单方法是提供在完成提交时要调用的回调方法。但是,您必须对用于进行该调用的原始 CommittableTransaction 对象调用 EndCommit 方法。要获取该对象,您可以终止回调方法的 IAsyncResult 参数,因为 CommittableTransaction 类实现 IAsyncResult 类。
下面的示例说明如何进行异步提交。
public void DoTransactionalWork() { Transaction oldAmbient = Transaction.Current; CommittableTransaction committableTransaction = new CommittableTransaction(); Transaction.Current = committableTransaction; try { /* Perform transactional work here */ // No errors - commit transaction asynchronously committableTransaction.BeginCommit(OnCommitted,null); } finally { //Restore the ambient transaction Transaction.Current = oldAmbient; } } void OnCommitted(IAsyncResult asyncResult) { CommittableTransaction committableTransaction; committableTransaction = asyncResult as CommittableTransaction; Debug.Assert(committableTransaction != null); try { using(committableTransaction) { committableTransaction.EndCommit(asyncResult); } } catch(TransactionException e) { //Handle the failure to commit } }
桂棹兮兰桨,击空明兮溯流光。