即使存在第二个服务错误,TransactionScope也允许部分更新

时间:2009-11-26 09:00:32

标签: c# .net transactions transactionscope

我已经通过相关问题进行了很好的拖网并实施了建议,但我仍然遇到.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页面后面的代码启动事务。

1 个答案:

答案 0 :(得分:1)

编辑:抱歉让事情倒退。

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

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

基本上你需要:

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

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

如果服务方法因异常而失败,则会投票支持该事务失败。