2014-01-10 10 views
6

Ich muss in zwei Tabellen mit einer einzigen Transaktion einfügen, Abfrage, die unten implementieren müssen. zweitens erhalten Ausnahme bei SqlDataReader lesen = comm.ExecuteReader();ExecuteReader erfordert Befehl, um eine Transaktion zu haben, wenn die Verbindung zugewiesen ist Befehl in ausstehende lokale trans

public void SqlExecuteNonQuery(Customer obj) 
{ 
    //string query = "DECLARE @_customerID int "; 
    string query1 = "INSERT INTO customer (customerName,customerSex,Email) VALUES ('" + obj.name + "','" + obj.sex + "','" + obj.Email + "') "; 
    //string query2 = "SET @_customerID [email protected]@identity "; 
    string query3 = "INSERT INTO customerDetails(customerID,customerAddress,customerPhone) VALUES (" + obj.id + ",'" + obj.address + "','" + obj.phone + "') "; 

    string CS = ConnectionName; 

    using (SqlConnection conn = new SqlConnection(CS)) 
    { 
    conn.Open(); 
    using (SqlCommand command = new SqlCommand("SELECT Email FROM Customer where Email ='" + obj.Email + "'", conn)) 
    { 
     SqlDataReader reader = command.ExecuteReader(); 

     try 
     { 
      if (reader.Read()) 
      { 
       throw new Exception("User already exist for the email"); 
      } 

      else 
      { 
       reader.Close(); 
       using (SqlCommand cmd = GetCommand(query1, conn)) 
       { 
        SqlTransaction transaction; 
        transaction = conn.BeginTransaction(); 

        try 
        { 
         cmd.Transaction = transaction; 
         cmd.ExecuteNonQuery(); 
         using (SqlCommand comm = new SqlCommand("Select customerID from Customer where email = '" + obj.Email + "'", conn)) 
         { 
          SqlDataReader read = comm.ExecuteReader(); 

          try 
          { 
          while (read.Read()) 
          { 
           obj.id = (int)read[0]; 
          } 
          using (SqlCommand cmd1 = GetCommand(query3, conn)) 
          { 
           try 
           { 
            cmd1.ExecuteNonQuery(); 
           } 
           catch (Exception ex1) 
           { 
            Console.WriteLine("Comit Exception Type: {0}", ex1.GetType()); 
            Console.WriteLine("error in inserting - {0}", ex1.Message); 
            try 
            { 
             transaction.Rollback(); 
            } 
            catch (Exception ex2) 
            { 
             Console.WriteLine("RollBack Exception Type: {0}", ex2.GetType()); 
             Console.WriteLine("Message: {0}", ex2.Message); 
            } 
           } 
          } 
          transaction.Commit(); 
          Console.WriteLine("Successfull transaction"); 

          } 
          catch (Exception ex) 
          { 
          Console.WriteLine("Error type:", ex.GetType()); 
          Console.WriteLine("Message:", ex.Message); 

          } 
          finally { 
          read.Close(); 
          } 

         } 
        } 

        catch (Exception ex) 
        { 
         Console.WriteLine("Comit Exception Type: {0}", ex.GetType()); 
         Console.WriteLine("error in inserting - {0}", ex.Message); 
         try 
         { 
          transaction.Rollback(); 
         } 
         catch (Exception ex2) 
         { 
         Console.WriteLine("RollBack Exception Type: {0}", ex2.GetType()); 
         Console.WriteLine("Message: {0}", ex2.Message); 
         } 
        } 
        finally 
        { 
         transaction.Dispose(); 
        } 
       } 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 

     } 
    } 
} 
+0

neuer Benutzer nicht beantwortet bis 8 Stunden. Die Ausnahme gibt eindeutig die Antwort. muss nur das sqlcommand-Objekt abarbeiten: D vor SqlDataReader reader = comm.ExecuteReader(); füge nur comm.Transaction = transaction hinzu; –

Antwort

7

Problem ist, dass Sie cmd1 auf derselben Verbindung wie cmd ausführen, so gibt es eine offene Transaktion auf dieser Verbindung ist aber nicht setzen cmd1.Transaction ... so Lösung

cmd1.Transaction = transaction; 
wäre

vor

cmd1.ExecuteNonQuery(); 
5

vielleicht möchten Sie mit TransactionScope Umschalten zu berücksichtigen, die dann für alle Befehle innerhalb implizit verwendet wird. Sie würden es so etwas wie verwenden:

using(var scope = new TransactionScope()) 
{ 
    using(var conn = new SqlConnection(/*...*/)) 
    { 
     //As many nested commands, etc, using the above connection. 
     //but don't need to create a SqlTransaction object nor 
     //in any way reference the scope variable 
    } 
    scope.Complete(); 
} 
+4

** Niemals ** 'new TransactionScope()' verwenden, ohne TransactionOptions anzugeben: http://blogs.msdn.com/b/drobwe/archive/2010/05/21/using-new-transactionscope-considired-harmful.aspx –

Verwandte Themen