8

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

就像是

  TransactionConfig.DisablePromotion = true;
4

3 回答 3

11

不,您不能通过属性或配置禁用交易促销。禁用事务提升的唯一方法是避免导致事务提升为分布式事务的条件。

为避免事务管理升级,您需要:

  • 使用 SQL Server 2005 或更高版本作为数据库

  • 如果是 SQL Server 2005,则在事务的生命周期内仅使用一个数据库连接。(SQL Server 2008 将允许您在事务中使用多个连接而不会发生升级。)

  • 只访问一个数据库

  • 不跨应用程序域传递您的事务


制定规则的原因是为了确保事务的ACID 属性

作为一个例子,让我们假设您可以指定不提升事务(如在您的代码片段中)但您的代码访问两个数据库(我知道 - 您的代码只使用一个数据库)。所以现在你已经指定不使用分布式事务,你已经启动了一个事务,并且你已经指定了两个数据库都应该在一个工作单元内。事务的 ACID 属性与避免分布式事务的愿望之间存在冲突。在我看来,有两种方法可以处理这个问题:要么将事务提升为分布式事务(你说你不想这样做!),要么抛出异常(因为你不能保证交易)。

因此,使用 DisablePromotion 属性不会有太大价值,因为应用程序要不促进事务,您仍然需要遵循升级规则

如果你真的想要,你可以处理DistributedTransactionStarted事件并在分布式事务启动时抛出异常。这将保证您的应用程序没有使用分布式事务,但这可能不是您想要的。

于 2009-10-16T05:46:42.623 回答
3

我认为没有直接的方法可以禁用促销。您可能想查看导致事务提升的情况。Juval Lowy 写了一篇关于 System.Transactions的优秀白皮书(也可在此处下载)。他详细介绍了促销规则。

于 2009-10-09T09:01:41.363 回答
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();
        }
      }
    }
  }
}
于 2013-03-18T22:14:34.713 回答