.NET:如何禁用System.Transactions中的晋升?

8

是否可以在不支持分布式事务的情况下使用System.Transactions编程模型?

类似这样的东西。

  TransactionConfig.DisablePromotion = true;

你遇到了什么问题,让你想要禁用推广? - Mike Two
我使用链接服务器连接两个Sql Servers。对于链接服务器逻辑,我使用了显式事务,因此完整性非常好。但是当我完成链接服务器时,SQL Server不会释放内部连接。 当我的应用程序继续并使用隐式事务(为简单起见),它们总是针对一个数据库运行。但是晋升发生是因为链接服务器连接仍然打开。 - andreas
3个回答

11
不,您不能通过属性或配置禁用事务提升。禁用事务提升的唯一方法是避免导致事务提升到分布式事务的条件。
为了避免事务管理升级,您需要:
- 使用SQL Server 2005或更高版本作为您的数据库 - 如果使用SQL Server 2005,请在事务的生命周期内仅使用一个数据库连接。(SQL Server 2008将允许您在事务中使用多个连接而无需发生提升。) - 仅访问一个数据库 - 不要跨应用程序域传递事务
规则的原因是确保事务的ACID属性
例如,假设您可以指定不要推广交易(如代码片段中所示),但是您的代码访问两个数据库(我知道——您的代码只使用一个数据库)。因此,现在您已经指定不使用分布式事务,已经启动了一个事务,并且指定了两个数据库都应该在同一工作单元内。事务的ACID属性与避免分布式事务的愿望之间存在冲突。在我看来,处理这种情况有两种方式:要么将事务升级为分布式事务(您说您不想这样做!),要么抛出异常(因为无法保证事务的完整性)。
因此,使用禁用推广属性并没有太大价值,因为为了使应用程序不升级事务,您仍然需要遵循升级规则。
如果您真的想要,您可以处理DistributedTransactionStarted事件,并在启动分布式事务时引发异常。这将确保您的应用程序不使用分布式事务,但这可能不是您想要的。

3
如果您的交易因为访问了两个数据库而被推广,但您只在一个数据库中进行写入操作,那么您可以通过在访问另一个数据库时抑制事务来避免推广。即:using (new TransactionScope(TransactionScopeOption.Suppress, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted })) { // 访问另一个数据库 } - Kirk Woll

3
我认为没有直接禁用事务提升的方法。您可能需要查看导致事务提升的情况。Juval Lowy写了一篇优秀的白皮书(也可在此处下载),详细介绍了System.Transactions中的提升规则。请参考链接:白皮书这里可下载。

您还可以在http://msdn.microsoft.com/en-us/library/ms973865.aspx找到Juval Lowy的Introducing System.Transactions的HTML版本。 - Randy Levy
优秀的白皮书。非常感谢。 - Maarten

1
我正在使用禁用了MSDTC服务的以下代码。
var txOpts = new TransactionOptions
          {
            IsolationLevel = IsolationLevel.ReadCommitted, 
            Timeout = TimeSpan.FromMinutes(10)};

using (var tx = new TransactionScope(TransactionScopeOption.Suppress, txOpts))
{
  using (var db1 = new ObjectContext(connection1))
  {
    db1.Connection.Open();
    using (var db1tx = db1.Connection.BeginTransaction(
                                System.Data.IsolationLevel.ReadCommitted))
    {
      using (var db2 = new ObjectContext(connection2))
      {
        db2.Connection.Open();
        using (var db2tx = db2.Connection.BeginTransaction(
                          System.Data.IsolationLevel.ReadCommitted))
        {
          // do stuff

          db1.SaveChanges(false);
          db2.SaveChanges(false);

          db1tx.Commit();
          db2tx.Commit();
          tx.Complete();
        }
      }
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接