.net中的交易


144

在C#.Net 2.0中进行事务处理的最佳实践是什么?应该使用哪些类?需要注意的陷阱是什么?所有提交和回滚的东西。我刚刚开始一个项目,在将数据插入数据库时​​可能需要做一些事务。我们欢迎您提供任何交易或什至有关交易基本内容的链接。


这是在CodeProject上开始使用.NETTransactions的一个很好的例子。
米切尔卖家

Answers:


271

有两种主要的交易类型:连接交易和环境交易。连接事务(例如SqlTransaction)直接与db连接(例如SqlConnection)绑定,这意味着您必须不断传递连接-在某些情况下可以,但是不允许“创建/使用/释放”用法,并且不允许跨数据库工作。一个示例(格式化为空格):

using (IDbTransaction tran = conn.BeginTransaction()) {
    try {
        // your code
        tran.Commit();
    }  catch {
        tran.Rollback();
        throw;
    }
}

不太混乱,但仅限于我们的连接“ conn”。如果要调用其他方法,则现在需要传递“ conn”。

另一种方法是环境交易。.NET 2.0中的新功能,TransactionScope对象(System.Transactions.dll)允许在一系列操作中使用(合适的提供程序将自动注册环境事务)。这样可以很容易地改编为现有的(非事务性)代码,并可以与多个提供程序进行对话(尽管如果您与多个对话者进行交谈,则DTC会参与其中)。

例如:

using(TransactionScope tran = new TransactionScope()) {
    CallAMethodThatDoesSomeWork();
    CallAMethodThatDoesSomeMoreWork();
    tran.Complete();
}

请注意,这两种方法可以处理它们自己的连接(打开/使用/关闭/处理),但是它们将无声地成为环境事务的一部分,而无需我们传递任何内容。

如果您的代码错误,将在不使用Complete()的情况下调用Dispose(),因此它将回滚。支持预期的嵌套等,尽管您不能回滚内部事务但仍可以完成外部事务:如果有人不满意,则事务中止。

TransactionScope的另一个优点是它不仅仅与数据库绑定;任何支持交易的提供商都可以使用它。以WCF为例。甚至还有一些与TransactionScope兼容的对象模型(即具有回滚功能的.NET类-也许比备忘录更容易,尽管我自己从未使用过这种方法)。

总而言之,这是一个非常非常有用的对象。

一些警告:

  • 在SQL Server 2000上,TransactionScope将立即转到DTC。这在SQL Server 2005及更高版本中已修复,在您提升​​为DTC之前,您可以使用LTM(开销更少),直到您与2个来源等进行交谈为止。
  • 出现故障意味着您可能需要调整连接字符串

CSLA .NET 2.0支持TransactionScope对象!
Binoj Antony

这里的问题是,当您在第一个方法中有一个事务并且此方法(封装)不知道是否会从父事务中调用时。
Eduardo Molteni

1
@Eduardo-使用TransactionScope时这不是问题,使其非常有吸引力。这样的事务嵌套,并且只有最外部的提交。
Marc Gravell

我希望你还在听。您说过“周围有一些与TransactionScope兼容的对象模型”。你能指出我一些吗?谢谢。
majkinetor

1
再次,马克,另一个出色的解释。当您说“支持预期的嵌套”时,是针对方法(例如CallAMethodThatDoesSomeWork())中定义的事务块本身吗?还是在外部定义了transactionscope,这不是必需的?
Phil Cooper

11
protected void Button1_Click(object sender, EventArgs e)
   {


       using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
       {
           connection1.Open();

           // Start a local transaction.
           SqlTransaction sqlTran = connection1.BeginTransaction();

           // Enlist a command in the current transaction.
           SqlCommand command = connection1.CreateCommand();
           command.Transaction = sqlTran;

           try
           {
               // Execute two separate commands.
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
               command.ExecuteNonQuery();
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
               command.ExecuteNonQuery();

               // Commit the transaction.
               sqlTran.Commit();
               Label3.Text = "Both records were written to database.";
           }
           catch (Exception ex)
           {
               // Handle the exception if the transaction fails to commit.
               Label4.Text = ex.Message;


               try
               {
                   // Attempt to roll back the transaction.
                   sqlTran.Rollback();
               }
               catch (Exception exRollback)
               {
                   // Throws an InvalidOperationException if the connection 
                   // is closed or the transaction has already been rolled 
                   // back on the server.
                   Label5.Text = exRollback.Message;

               }
           }
       }


   }

4

您也可以将事务包装到它自己的存储过程中,并以这种方式处理它,而不是在C#本身中进行事务。



0

这也取决于您的需求。对于基本的SQL事务,您可以尝试通过在代码中使用BEGIN TRANS和COMMIT TRANS进行TSQL事务。这是最简单的方法,但是它确实很复杂,因此您必须小心进行正确的提交(和回滚)。

我会用类似的东西

SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
    ...
    Do SQL stuff here passing my trans into my various SQL executers
    ...
    trans.Commit  // May not be quite right
}

任何失败都会使您突然退出,using并且事务将始终提交或回滚(取决于您告诉它要执行的操作)。我们面临的最大问题是确保始终如一。使用确保交易范围是有限的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.