2010-12-12 40 views
3

J'essaie de comprendre comment fonctionne TransactionScope en jouant avec un exemple de code représentant différents scénarios de transactions ...
Pouvez-vous expliquer ce qui se passe réellement avec la date lorsque j'ai 2 TransactionScopes simultanés chacun avec sa propre connexion? Comme dans cet exemple de code:Deux TransactionScope parallèles chacun avec sa propre connexion

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

Répondre

4

champs de transaction qui sont imbriquées (et sur le même thread) faire partie de la même transaction (la transaction extérieure étant la portée déterminante pour l'achèvement) - escalade au DTC si nécessaire . Dans votre cas, les transactions ne semblent pas imbriquées, elles ne sont donc pas liées. Cela devrait également signifier que le LTM plutôt que DTC est le propriétaire, qui a moins de frais généraux. Par conséquent, il se peut bien sûr que vous deviez surveiller le blocage, entre autres, s'ils touchent les mêmes données. D'autant plus que la portée de la transaction est par défaut à l'isolation sérialisable.

+0

Ils ne sont pas liés oui, mais que se passe-t-il avec des données ici? En théorie, les transactions sont isolées, donc la première transaction devrait créer "db copy" et modifier cette copie, juste après la création de la première transaction, la seconde est créée et devrait avoir la même copie de données, car elle est créée avant la première validation. Puis 1er commit ses données, puis deuxième commit ses données, donc en gros je devrais avoir en résultat les données de la dernière transaction à valider, mais dans ce code le résultat est dead lock. –

+0

@Broken en effet; le * lire * ici est juste un verrou de lecture donc l'impasse est probable. Si j'écrivais TSQL j'ajouterais le UPDLOCK qui causerait le blocage plutôt que l'interblocage. Je ne sais pas si vous pouvez ajouter UPDLOCK pour lire avec EF –

+0

@Broken sur le scénario - la première validation ne peut pas se produire si le second thread a un verrou en lecture. La suggestion UPDLOCK ci-dessus fonctionnerait en empêchant le deuxième thread de lire les données jusqu'à ce que le premier thread ait terminé son travail. –