2010-12-12 8 views
3

Ich versuche herauszufinden, wie TransactionScope um Beispielcode mit verschiedenen Transaktionsszenarien herumspielt ...
Können Sie erklären, was tatsächlich mit dem Datum passiert, wenn ich jeweils zwei gleichzeitige TransactionScopes habe mit seiner eigenen Verbindung? Wie in diesem Beispielcode:Zwei parallele TransactionScope mit jeweils eigener Verbindung

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

Antwort

4

Transaktions Scopes, die nested (und auf dem gleichen Thread) Teil der gleichen Transaktion werden (die äußere Transaktion definierenden Geltungsbereich für die Fertigstellung ist) - zu DTC eskaliert, wenn nötig . In Ihrem Fall scheinen die Transaktionen nicht verschachtelt zu sein, also sind sie nicht verwandt. Das sollte auch bedeuten, dass der LTM und nicht DTC der Eigentümer ist, der weniger Overhead hat.

Daher müssen Sie möglicherweise zwischen diesen Blöcken suchen, wenn sie die gleichen Daten berühren. Vor allem, da der Transaktionsbereich standardmäßig serialisierbar ist.

+0

Sie sind nicht verwandt ja, aber was passiert hier mit Daten? Theoretisch sind Transaktionen isoliert, so dass die erste Transaktion "db copy" erstellen und diese Kopie modifizieren sollte, direkt nach der ersten Transaktionserstellung, wird zweitens erstellt und sollte dieselbe Datenkopie haben, da sie vor dem ersten Commit erstellt wird. Dann setze ich die Daten ein, und dann beginne ich ihre Daten, also sollte ich im Ergebnis die Daten der letzten zu übertragenden Transaktion haben, aber in diesem Code ist das Ergebnis ein Deadlock. –

+0

@Broken tatsächlich; Das * Lesen * hier ist nur eine Lesesperre, so dass ein Deadlock wahrscheinlich ist. Wenn ich TSQL schreiben würde, würde ich den UPDLOCK hinzufügen, der Blockierung anstatt Deadlock verursachen würde. Ich weiß nicht, ob Sie UPDLOCK zum Lesen mit EF –

+0

@Broken für das Szenario hinzufügen können - das erste Commit kann nicht passieren, wenn der zweite Thread eine Lesesperre hat. Der obige UPDLOCK-Vorschlag würde funktionieren, indem * verhindert wird, dass der zweite Thread die Daten liest, bis der erste Thread seine Arbeit beendet hat. –

Verwandte Themen