本地事务 (ADO.NET)

如果要将多项任务绑定在一起,使其作为单个工作单元来执行,可以使用 ADO.NET 中的事务。 例如,假设应用程序执行两项任务。 首先使用订单信息更新表。 然后更新包含库存信息的表,将已订购的商品记入借方。 如果任何一项任务失败,两个更新均将回滚。

确定事务类型

事务如果是单阶段事务,并且由数据库直接处理,则属于本地事务。 事务如果由事务监视程序进行协调并使用故障保护机制(例如两阶段提交)解决事务,则属于分布式事务。

每个 .NET Framework 数据提供程序使用自己的 Transaction 对象来执行本地事务。 如果要求在 SQL Server 数据库中执行,请选择 System.Data.SqlClient 事务。 对于 Oracle 事务,使用 System.Data.OracleClient 提供程序。 此外,还提供了一个新的 DbTransaction 类,用于编写需要事务并且与提供程序无关的代码。

注意注意

在服务器上执行时,事务最有效。如果使用的 SQL Server 数据库广泛使用显式事务,应考虑使用 Transact-SQL BEGIN TRANSACTION 语句以存储过程的形式编写这些事务。有关执行服务器端事务的更多信息,请参见“SQL Server 联机图书”。

使用单个连接执行事务

在 ADO.NET 中,使用 Connection 对象控制事务。 可以使用 BeginTransaction 方法启动本地事务。 开始事务后,可以使用 Command 对象的 Transaction 属性在该事务中登记一个命令。 然后,可以根据事务组件的成功或失败,提交或回滚在数据源上进行的修改。

注意注意

不应对本地事务使用 EnlistDistributedTransaction 方法。

事务的作用域限于该连接。 以下示例执行显式事务,该事务由 try 块中两个独立的命令组成。 这两个命令对 AdventureWorks SQL Server 2005 示例数据库的 Production.ScrapReason 表执行 INSERT 语句,如果没有引发异常,则提交。 如果引发异常,catch 块中的代码将回滚事务。 如果在事务完成之前事务中止或连接关闭,事务将自动回滚。

示例

按照下列步骤执行事务。

  1. 调用 SqlConnection 对象的 BeginTransaction 方法,以标记事务的开始。 BeginTransaction 方法返回对事务的引用。 此引用分配给在事务中登记的 SqlCommand 对象。

  2. 将 Transaction 对象分配给要执行的 SqlCommandTransaction 属性。 如果在具有活动事务的连接上执行命令,并且尚未将 Transaction 对象配给 Command 对象的 Transaction 属性,则会引发异常。

  3. 执行所需的命令。

  4. 调用 SqlTransaction 对象的 Commit 方法完成事务,或调用 Rollback 方法结束事务。 如果在 CommitRollback 方法执行之前连接关闭或断开,事务将回滚。

以下代码示例演示对 Microsoft SQL Server 使用 ADO.NET 的事务逻辑。

Using connection As New SqlConnection(connectionString)
    connection.Open()

    ' Start a local transaction.
    Dim sqlTran As SqlTransaction = connection.BeginTransaction()

    ' Enlist a command in the current transaction.
    Dim command As SqlCommand = connection.CreateCommand()
    command.Transaction = sqlTran

    Try
        ' Execute two separate commands.
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
        command.ExecuteNonQuery()
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
        command.ExecuteNonQuery()

        ' Commit the transaction
        sqlTran.Commit()
        Console.WriteLine("Both records were written to database.")

    Catch ex As Exception
        ' Handle the exception if the transaction fails to commit.
        Console.WriteLine(ex.Message)

        Try
            ' Attempt to roll back the transaction.
            sqlTran.Rollback()

        Catch exRollback As Exception
            ' Throws an InvalidOperationException if the connection 
            ' is closed or the transaction has already been rolled 
            ' back on the server.
            Console.WriteLine(exRollback.Message)
        End Try
    End Try
End Using
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

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

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

    try
    {
        // Execute two separate commands.
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
        command.ExecuteNonQuery();
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
        command.ExecuteNonQuery();

        // Commit the transaction.
        sqlTran.Commit();
        Console.WriteLine("Both records were written to database.");
    }
    catch (Exception ex)
    {
        // Handle the exception if the transaction fails to commit.
        Console.WriteLine(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.
            Console.WriteLine(exRollback.Message);
        }
    }
}

请参见

概念

分布式事务 (ADO.NET)

SQL Server 的 System.Transactions 集成 (ADO.NET)

其他资源

事务和并发 (ADO.NET)