2010-12-12 58 views
3

我想弄清楚TransactionScope如何在代表不同交易场景的示例代码中玩弄...
你能解释一下当我有两个并发TransactionScopes有它自己的连接?像在此示例代码:两个并行的TransactionScope每个都有它自己的连接

internal class Program 
{ 
    private const int Count = 20; 
    private static readonly Random Random = new Random(); 

    private static void Main(string[] args) 
    { 
     var task1 = new Task(Task1); 
     var task2 = new Task(Task2); 
     task1.Start(); 
     task2.Start(); 
     Console.ReadLine(); 
    } 
    private static void Task1() 
    { 
     var connection = new EntityConnection("name=ModelContainer"); 
     using (var transaction = new TransactionScope()) 
     { 
      DoWork(connection); 
      transaction.Complete(); 
     } 
    } 
    private static void Task2() 
    { 
     var connection = new EntityConnection("name=ModelContainer"); 
     using (var transaction = new TransactionScope()) 
     { 
      DoWork(connection); 
      transaction.Complete(); 
     } 
    } 
    private static void DoWork(EntityConnection connection) 
    { 
     connection.Open(); 
     using (var context = new ModelContainer(connection)) 
     { 
      List<SyncData> list = context.SyncDataSet.ToList(); 
      for (int i = 0; i < Count; i++) 
      { 
       list[i].Knowledge.Version = Random.Next(200); 
       context.SaveChanges(); 
      } 
     } 
    } 
} 

回答

4

事务范围是嵌套(和在相同的线程)成为同一个事务(外部事务是用于完成限定范围)的一部分 - 如果需要升级到DTC 。在你的情况下,交易似乎并不嵌套,所以它们不相关。这也意味着LTM而不是DTC是所有者,其开销较小。

因此,当然,如果他们触及相同的数据,您可能需要在这些间隔之间观察阻塞等。特别是因为事务范围默认为可序列化隔离。

+0

他们不相关是的,但这里的数据发生了什么?理论上,事务是孤立的,所以第一个事务应该创建“db copy”并在创建第一个事务之后修改该副本,第二个事务创建并且应该具有相同的数据副本,因为它是在第一次提交之前创建的。然后第一次提交它的数据,然后第二次提交它的数据,所以基本上我应该得到最后一个事务的数据提交,但在这段代码中,结果是死锁。 – 2010-12-12 19:19:05

+0

@的确确; * read *在这里只是一个读锁,所以可能会发生死锁。如果我写TSQL,我会添加UPDLOCK,这会导致阻塞而不是死锁。我不知道你是否可以添加UPDLOCK来读取EF – 2010-12-12 19:24:44

+0

@Broken这个场景 - 如果第二个线程有一个读锁定,则不会发生第一次提交。上面的UPDLOCK建议可以通过阻止第二个线程读取数据直到第一个线程完成它的工作。 – 2010-12-12 19:26:42

相关问题