2011-07-19 50 views
3

我有几个方法 - 几个调用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: The transaction under which this method call was executing was asynchronously aborted."

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

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(); 
    } 

如果事务被认为是孤立的,为什么多个线程调用方法冲突?

回答

2

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

尝试使用具有Single或Reentrant并发模式的System.ServiceModel.ServiceBehaviorAttribute.ConcurrencyMode属性。我想这就是你的期望。

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)] 

我猜你得到了异常,因为IsolationLevel.Serializable将使第二个线程访问易失性数据,但不会让它去改变它。你应该做一些改变操作,这种隔离级别是不允许的。