2016-03-25 4 views
0

Ich versuche sicherzustellen, dass sowohl meine einfügen und darunter löschen funktioniert vollständig oder gar nicht. Ich habe mein Verbindungsobjekt außerhalb meines Transaktionsbereichs, was meiner Meinung nach nicht hundertprozentig sicher ist.TransactionScope scheint nicht zu funktionieren

Ich weiß, dass dieser Code nicht so funktioniert, wie ich es vorhabe. Nach dem ersten Teil (der Einfügevorgang) und dem Abbruch durch Abbruch an einem Unterbrechungspunkt werden die Zeilen tatsächlich eingefügt, obwohl ich scope.complete nie aufgerufen habe.

Bitte zeigen Sie den Fehler in meinem Denken und Logik hier.

   sqlConnection.Open(); 

       int numFound = 1; 
       int max = 99; 
       int iteration = 0; 
       while (iteration < max && numFound > 0) 
       { 
        iteration++; 
        var ids = new List<int>(); 
        using (var sqlCommand0 = new SqlCommand(sql0, sqlConnection)) 
        { 
         using (SqlDataReader reader1 = sqlCommand0.ExecuteReader()) 
         { 
          while (reader1.Read()) 
          { 
           ids.Add(reader1.GetInt32(0)); 
          } 
         } 
        } 
        numFound = ids.Count; 
        if (numFound > 0) 
        { 
         using (var scope = new TransactionScope()) 
         { 
          string whereClause = $"WHERE Id IN ({string.Join(",", ids)})"; 

          string sql1 = string.Format(sqlTemplate1, whereClause); 
          using (var sqlCommand1 = new SqlCommand(sql1, sqlConnection)) 
          { 
           sqlCommand1.ExecuteNonQuery(); 
          } 

          // BREAK POINT HERE - ABORTED PROGRAM AND sql1 had been committed. 

          var sql2 = "DELETE FROM SendGridEventRaw " + whereClause; 
          using (var sqlCommand2 = new SqlCommand(sql2, sqlConnection)) 
          { 
           sqlCommand2.ExecuteNonQuery(); 
          } 
          scope.Complete(); 
          total += numFound; 
          Console.WriteLine("deleted: " + whereClause); 
         } 
        } 
       } 
      } 

Antwort

3

Ich denke es ist, weil Sie Ihre Verbindung öffnen, bevor Sie Ihre Transaktion starten. Sie könnten versuchen, Ihr Problem zu beheben, indem Sie zuerst Ihre Transaktion starten und dann Ihre Verbindung öffnen.

0

Nur von dem, was ich sehe und was ich gehe davon aus, was Sie beabsichtigen dies zu geschehen ist: Wenn Ihre erste Abfrage einige Datensätze bekommt, dann wird die nächste Abfrage ausgeführt wird, damit die Aussage:

if (numFound > 0) 

Wenn das der Fall ist, und wo Sie Ihren Haltepunkt setzen, ist wahr, natürlich wird die INSERT-Anweisung ausgelöst. Grund ist:

using (var sqlCommand1 = new SqlCommand(sql1, sqlConnection)) 
          { 
           sqlCommand1.ExecuteNonQuery(); 
          } 

ist innerhalb dieser if-Anweisung. Sie sagen "Wenn Zeilen vorhanden sind, führen Sie die Einfügeabfrage aus."

Wenn Sie versuchen, das scope-Objekt tatsächlich zu erhalten, um die Abfrage auszuführen, dann müssen Sie den gesamten Abfrageaufbau innerhalb des Objekts ausführen und dann scope.complete() ausführen.

Zum Beispiel:

//In TransactionScope class 

public string Complete(var ids, int numFound, SqlConnection sqlConnection, string sqlTemplate1) 
{ 
    string whereClause = $"WHERE Id IN ({string.Join(",", ids)})"; 

          string sql1 = string.Format(sqlTemplate1, whereClause); 
          using (var sqlCommand1 = new SqlCommand(sql1, sqlConnection)) 
          { 
           sqlCommand1.ExecuteNonQuery(); 
          } 

          var sql2 = "DELETE FROM SendGridEventRaw " + whereClause; 
          using (var sqlCommand2 = new SqlCommand(sql2, sqlConnection)) 
          { 
           sqlCommand2.ExecuteNonQuery(); 
          } 
          return whereClause; 
} 


//in your Main class 

if (num > 0) 
{ 
    string whereClause = scope.Complete(ids, numFound, sqlConnection, sqlTemplate1); 
    Console.WriteLine("deleted" + whereClause"."); 
} 

, von denen ich natürlich gehen gerade weg von den Annahmen, die ich oben erwähnt. Wenn ich falsch bin, lass es mich wissen.

Ich hoffe, es hilft.