【问题标题】:TransactionScope Allows Partial Update Even Though Second Service Errors即使第二次服务错误,TransactionScope 也允许部分更新
【发布时间】:2009-11-26 18:42:19
【问题描述】:

我已经很好地搜索了相关问题并找到了实施的建议,但我仍然遇到 .NET TransactionScope 的问题。

我正在从一个方法调用两个 WCF 服务,即使第二个服务出错(在这种情况下是故意的),第一个服务也不会回滚。我创建了一个简单的测试应用程序来演示这个问题。

调用方法如下:

private void TryATransaction()
{
    ServiceReference1.IService1 service = new ServiceReference1.Service1Client();
    ServiceReference2.IService1 service2 = new ServiceReference2.Service1Client();

    using (TransactionScope scope = new TransactionScope())
    {
        service.TestMethod("one");
        service2.UpdateSomethingElse("two");

        scope.Complete();
    }
}

第一个服务看起来像这样(匿名连接):

public bool TestMethod(string anything)
{
        using (TransactionScope scope = new TransactionScope())
        {

            // connect to a db
            using (SqlConnection connection = new SqlConnection("Data Source=DATASOURCE;Initial Catalog=DATABASE;Integrated Security=SSPI;Transaction Binding=Explicit Unbind;"))
            {

                connection.Open();
                // save something
                SqlCommand command1 = new SqlCommand("EXECUTE [DATABASE].[dbo].[uspUpdateCustomer] 3, 'test@test.com', 1, null", connection);
                command1.ExecuteNonQuery();
                connection.Close();

            }

            scope.Complete();
        }

    return true;
}

第二个服务与第一个服务相同,只是它更新了数据库中的不同字段。

1) 如果我在没有强制错误的情况下运行它,它会更新所有字段。

2) 当我运行它并在第二个服务中强制出错时,第一个服务的更新被提交到数据库,而第二个服务被回滚(错误出现在 ExecuteNonQuery 语句之后)。

此示例代码基本上遵循此处找到的示例: http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

我添加了 Explicit Unbind,这是在其他相关问题中推荐的。

非常欢迎您提出建议 - 如果需要,我很乐意添加更多信息。

额外信息

分布式标识符似乎一直都是 00000000-0000-0000-0000-000000000000 - 我不知道这是否是一个线索。

这里是分布式 id 和本地 id 的 dubug 输出(按顺序)

当前交易是 00000000-0000-0000-0000-000000000000 - f6446876-496d-488c-a21c-1e4c4295d50c:8

当前交易是 00000000-0000-0000-0000-000000000000 - 7edd5ba3-7f5a-42af-b9ca-37b3862c26a7:2

当前交易是 00000000-0000-0000-0000-000000000000 - 6fa0e3f7-b655-40ad-8bdd-f0670de79a49:2

事务是通过我的示例应用程序中的 aspx 页面后面的代码启动的。

【问题讨论】:

  • 一个问题:(可能是愚蠢的一个):查看代码,我们期望 TransactionScope 可以跨客户端和服务器边界工作;支持吗?

标签: c# .net transactions transactionscope


【解决方案1】:

编辑:对不起,事情倒退了。

问题很可能是由于将事务与 WCF 一起使用造成的。

查看this 关于事务服务的文章。特别是关于客户端/服务模式事务的部分。

基本上你需要:

  • 在 OperationContract 接口方法上设置 [TransactionFlow(TransactionFlowOption.Mandatory)] 属性
  • 在其实现中设置[OperationBehavior(TransactionScopeRequired = true)] 属性
  • TransactionFlowBindingElement 添加到服务的BindingContext
  • 从您的服务实现中删除 TransactionScope,因为您使用的是客户端的 TransactionScope。

成功完成的每个服务方法都会投票决定事务是否成功(当您使用默认的 TransactionAutoComplete=true OperationBehavior 时)。

如果服务方法由于异常而失败,它会投票支持事务失败。

【讨论】:

  • 是的 - 这些属性似乎是关键 - 感谢您回来调整!
猜你喜欢
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 2023-03-13
  • 2020-09-19
  • 1970-01-01
  • 2012-11-08
相关资源
最近更新 更多