7

我已经看到System.Transactions命名空间,并且想知道,我真的可以使用这个命名空间使用 RDMBS 吗?

但是当我看到一些例子时,我不明白 System.Transactions 除了简单的 try catch 和让我们获得成功/失败结果之外如何做任何事情?

这是 MSDN 网站上的示例,我知道它可能非常简单,但我无法理解此示例中的好处,有人可以告诉我以下示例中简单的 try/catch 和 Transaction 范围之间的区别。

如果我应该创建一个 RDBMS(创建我自己的 RDMBS),我知道我们必须将我们执行的操作的大量日志写入磁盘,最后我们在回滚的情况下撤消这些操作,但这里什么都没有关于撤消任何事情。

// 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);
    }
    catch (ApplicationException ex)
    {
        writer.WriteLine("ApplicationException Message: {0}", ex.Message);
    }

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

    return returnValue;
}

在上面的例子中,我们提交了什么?我猜 SQL 客户端库会做所有正确的事情吗?这是否意味着 System.IO.StringWriter 将包含所有成功文本或所有失败文本?或者 TransactionScope 的范围之间是否有任何锁定?

4

2 回答 2

3

First of all TransactionScope is not the same as try/catch. TransactionScope is by the name scope of a transaction. Transaction in scope has to be explicitly commited by calling Complete on the scope. Any other case (including exception raised in scope) results in finishing using block which disposes the scope and implicitly rollback the incomplete transaction but it will not handle the exception.

In basic scenarios transaction from System.Transactions behaves same as db client transaction. System.Transactions provides following additional features:

  • API agnostic. You can use same transaction scope for oracle, sql server or web service. This is important when your transaction is started in layer which is persistance ignorant (doesn't know any information about persistance implementation).
  • Automatic enlistment. If specified on connection string (default behavior). New database connection automatically enlists into existing transaction.
  • Automatic promotion to distributed transaction. When second connection enlists to transaction it will be automatically promoted to distirbuted one (MSDTC is needed). Promotion also works when you enlist other coordinated resource like transactional web service.
  • etc.
于 2010-08-21T10:21:10.873 回答
1

事务将为您进行必要的锁定。此外,如果事务未由 Complete() 提交(如评论所建议的那样),则当事务在其范围结束时被处置时,还有一个隐式回滚。所以万一出现异常,所有操作都会自动回滚,数据库不会发生任何变化。例如,如果第二个查询失败,它也会使第一个查询的更改被丢弃。

但是对于 StringWriter,它仍然会包含直到故障点的消息(例如

Rows to be affected by command1: {0}
ApplicationException Message: {0}

都可以在此代码之后出现在您的日志中。

至于用这个类创建一个 RDBMS,我不确定我是否理解你的问题。如果您想实际创建一个关系数据库管理系统,我会说您可能看错了地方。如果您的意思是要通过事务访问 RDBMS,我会说,这取决于您的需求,即。如果您需要能够保证您的语句以全有或全无的方式按顺序运行的事务,那么是的,事务是一个很好的起点。

于 2010-08-21T09:55:11.163 回答