0

我对相关问题和实施的建议进行了很好的搜索,但我仍然对 .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 页面后面的代码启动的。

4

1 回答 1

1

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

该问题很可能是由于将事务与 WCF 一起使用所致。

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

基本上你需要:

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

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

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

于 2009-11-26T09:25:04.020 回答