C# TransactionScope.Complete 方法如何使用

示例

以下示例演示如何使用 TransactionScope 类定义代码块以参与事务。


C#

复制
// This function takes arguments for 2 connection strings and commands to create a transaction 
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the 
// transaction is rolled back. To test this code, you can connect to two different databases 
// on the same server by altering the connection string, or to another 3rd party RDBMS by 
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
    string connectString1, string connectString2,
    string commandText1, string commandText2)
{
    // Initialize the return value to zero and create a StringWriter to display results.
    int returnValue = 0;
    System.IO.StringWriter writer = new System.IO.StringWriter();

    try
    {
        // Create the TransactionScope to execute the commands, guaranteeing
        // that both commands can commit or roll back as a single unit of work.
        using (TransactionScope scope = new TransactionScope())
        {
            using (SqlConnection connection1 = new SqlConnection(connectString1))
            {
                // Opening the connection automatically enlists it in the 
                // TransactionScope as a lightweight transaction.
                connection1.Open();

                // Create the SqlCommand object and execute the first command.
                SqlCommand command1 = new SqlCommand(commandText1, connection1);
                returnValue = command1.ExecuteNonQuery();
                writer.WriteLine("Rows to be affected by command1: {0}", returnValue);

                // If you get here, this means that command1 succeeded. By nesting
                // the using block for connection2 inside that of connection1, you
                // conserve server and network resources as connection2 is opened
                // only when there is a chance that the transaction can commit.   
                using (SqlConnection connection2 = new SqlConnection(connectString2))
                {
                    // The transaction is escalated to a full distributed
                    // transaction when connection2 is opened.
                    connection2.Open();

                    // Execute the second command in the second database.
                    returnValue = 0;
                    SqlCommand command2 = new SqlCommand(commandText2, connection2);
                    returnValue = command2.ExecuteNonQuery();
                    writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
                }
            }

            // The Complete method commits the transaction. If an exception has been thrown,
            // Complete is not  called and the transaction is rolled back.
            scope.Complete();
        }
    }
    catch (TransactionAbortedException ex)
    {
        writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
    }

    // Display messages.
    Console.WriteLine(writer.ToString());

    return returnValue;
}

注解

如果确信范围内的所有操作都已成功完成,则只应调用此方法一次,以通知事务管理器所有资源的状态都是一致的,并且可以提交事务。 最好将调用作为块中的 using 最后一个语句。

未能调用此方法会中止事务,因为事务管理器将此解释为系统故障或在事务范围内引发的异常。 但是,还应注意,调用此方法并不能保证事务的提交。 它只是一种将状态通知给事务管理器的方式。 调用此方法后,无法再通过 Current 属性访问环境事务,并且尝试这样做会导致引发异常。

如果 TransactionScope 对象创建了事务,则资源管理器之间的实际提交工作将发生在 End Using 语句中。 如果该对象未创建事务,则每当 Commit 对象的所有者调用 CommittableTransaction 时都会执行提交。 此时,事务管理器会调用资源管理器,并根据是否在 对象上 TransactionScope 调用此方法来通知它们提交或回滚。