5

考虑以下方法。

DoA()
{
  using (TransactionScope scope = new TransactionScope)
  {
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
      connection.Open();
      SqlCommand command = new SqlCommand(query, connection);
      command.ExecuteNonReader();

      DoB();    

      scope.Complete();
    }
  }
}

DoB()
{
  using (TransactionScope scope = new TransactionScope)
  {
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
      connection.Open();
      SqlCommand command = new SqlCommand(query, connection);
      command.ExecuteNonReader();

      DoC();

      scope.Complete();
    }
  }
}

DoC()
{
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
    connection.Open();
    SqlCommand command = new SqlCommand(query, connection);
    command.ExecuteNonReader();
  }
}

如果我们调用DoA(),后续的交互是否会在DoB()与SQL Server 相关的 ' 事务DoC()的上下文中运行?DoA()DoC() 是否在DoA()DoB()的事务的上下文中运行?

(还是我严重误解了什么?)

4

2 回答 2

5

从逻辑上讲,所有代码都将是一个事务。嵌套范围不一定会创建新事务(除非您使用 RequiresNew),因此它将是单个事务。现在,每个作用域都必须投票以完成事务,因此在您的第二个作用域中,如果您删除Complete, 应该会导致整个事务回滚。

DoC 也将成为交易的一部分;环境事务将检测新连接并自动登记。

请阅读此处的所有详细信息,这些详细信息解释了在环境事务中注册的行为以及不同的选项RequiresRequiresNewSuppress

另请注意,如果您的连接不使用完全相同的连接字符串,这将自动将整个事务提升为分布式事务。只是需要注意的事情。

于 2013-04-19T17:00:12.447 回答
2

根据安迪的评论编辑:

好像这样的事情会在 SQL 服务器上发生:

BEGIN TRANSACTION A

  -- do A's work

  -- B does NOT create a new transaction

    -- do B's work

    -- do C's work

COMMIT TRANSACTION A

new TransactionScope(TransactionScopeOption.RequiresNew)如果在 中使用,会发生以下情况DoB()

BEGIN TRANSACTION A

  -- do A's work

  BEING TRANSACTION B

    -- do B's work

    -- do C's work

  COMMIT TRANSACTION B
COMMIT TRANSACTION A
于 2013-04-18T21:54:39.823 回答