为什么这笔交易不是孤立的?

时间:2011-07-19 14:23:05

标签: wcf concurrency transactions

我有几个方法 - 几次调用SQL Server和一些业务逻辑来生成唯一值。这些方法都包含在父方法中:

GenerateUniqueValue()
{
  //1. Call to db for last value
  //2. Business logic to create new value
  //3. Update db with new value created
}

我希望隔离对GenerateUniqueValue的调用,即 - 当两个客户端同时调用它时,第二个客户端必须等待第一个客户端完成。

最初,我的服务是单身人士;但是,我必须预测未来可能包括负载平衡的变化,所以我认为单独的方法已经出来了。接下来,我决定通过装饰我的服务来尝试交易方法:

[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Serializable, TransactionTimeout = "00:00:30")]

我的GenerateUniqueValue:

[OperationBehavior(TransactionScopeRequired = true)]

问题是对服务方法的同时命中测试会导致错误:

  

“System.ServiceModel.ProtocolException:执行此方法调用的事务是异步中止的。”

这是我的客户端测试代码:

private static void Main(string[] args)
    {

        List<Client> clients = new List<Client>();
        for (int i = 1; i < 20; i++)
        {
            clients.Add(new Client());
        }

        foreach (var client in clients)
        {
            Thread thread = new Thread(new ThreadStart(client.GenerateUniqueValue));
            thread.Start();
        }

        Console.ReadLine();
    }

如果假设事务被隔离,为什么多个线程调用该方法会发生冲突?

1 个答案:

答案 0 :(得分:2)

事务用于将多个操作视为单个原子操作。因此,如果你想让第二个线程等待第一个线程的完成,你必须处理并发而不是事务。

尝试将System.ServiceModel.ServiceBehaviorAttribute.ConcurrencyMode属性与单一或重入并发模式一起使用。我猜这就是你所期待的。

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]

我猜你得到了异常,因为IsolationLevel.Serializable会使第二个线程能够访问volatile数据,但不会让它改变它。您可能正在进行一些不允许使用此隔离级别的更改操作。

相关问题