2017-04-19 6 views
0

Ich habe ein .exe Projekt mit 4 Threads. Jeder Thread ruft einen WCF-Dienst auf, der in einem Windows-Dienst gehostet wird, und fügt einen Datensatz ein (Schleife von 1 bis 5.000 Datensätzen). Das Testprojekt wird versuchen, 20.000 Datensätze in den WCF-Dienst einzufügen. Das Dienstverhalten in dem WCF-Dienst ist pro Sitzung.C# SqlCommand Rückgabe von Eingabeparametern beim Einfügen mehrerer Datensätze

Ich verwende eine gespeicherte Prozedur, um die Datensätze in SQL Server 2008R2 Express einzufügen. Das Problem, das ich habe, ist mit der SqlCommand. Wenn nur ein Thread ausgeführt wird, tritt kein Fehler auf, aber wenn zwei oder mehr Threads ausgeführt werden, gibt der Code einen Fehler aus, aber nicht sicher über den Fehlertyp.

Wenn Sie sich den folgenden Code ansehen, wird der Fehler beim Lesen des Ergebnisses von .ExecuteReader ausgelöst (es handelt sich um einen Cast-Ausnahmefehler). Es gibt nicht die Fehler zurück, die ich in der gespeicherten Prozedur definiert habe (ich vermute, dass es nie in die Datenbank gelangt), es gibt ein XML mit allen Parametern des txn-Datensatzes zurück, aber es gibt nicht nur die aktuelle Transaktion zurück, Es gibt auch einen Datensatz von Transaktionen zurück, die in einem anderen Thread ausgeführt werden. Wenn ich die gespeicherte Prozedur direkt in SQL Server Management Studio ausführe, funktioniert es einwandfrei, sodass ich jedes Problem auf Isolationsstufe auf der Datenbankseite verworfen habe.

Wie Sie sehen können, ist die Methode nicht statisch, die SqlCommand wird bei jedem Aufruf erstellt und entsorgt, so dass ich wirklich darüber besorgt bin. Irgendwelche Ideen?

private InsertInvoiceDataTable SaveTransaction(Transaction Trans, ClientInfo InfoCliente) 
    { 
     InsertInvoiceDataTable returnData = new InsertInvoiceDataTable(); 

     try 
     { 
      using (SqlConnection con = new SqlConnection(ConnStr1) 
      { 

       using (SqlCommand cmd = new SqlCommand("InsertInvoice", con)) 
       { 
        cmd.CommandType = CommandType.StoredProcedure; 

        cmd.Parameters.Add("@TIPO", SqlDbType.Int).Value = Trans.InvoiceType; 
        cmd.Parameters.Add("@CAJERO", SqlDbType.VarChar).Value = Trans.Cashier; 
        cmd.Parameters.Add("@TERMID", SqlDbType.Int).Value = Trans.Term; 
        cmd.Parameters.Add("@DOB", SqlDbType.DateTime).Value = Trans.DOB; 
        cmd.Parameters.Add("@CLIID", SqlDbType.VarChar).Value = InfoCliente.ClientId; 
        cmd.Parameters.Add("@VENTANETA", SqlDbType.Decimal).Value = Convert.ToDecimal(Trans.SubTotal); 
        cmd.Parameters.Add("@IMPUESTO", SqlDbType.Decimal).Value = Convert.ToDecimal(Trans.TaxTotal); 
        cmd.Parameters.Add("@VENTATOTAL", SqlDbType.Decimal).Value = Convert.ToDecimal(Trans.Total);      

        con.Open(); 

        using (SqlDataReader results = cmd.ExecuteReader()) 
        { 
         while (results.Read()) 
          { 
           InsertInvoiceRow row = returnData.NewInsertInvoiceRow(); 
           try 
           { 
            row.TIPO_log = results["Type_log"].ToString(); 
            row.VALOR_LOG = results["Value_log"].ToString(); 

           } 
           catch (Exception ex) 
           { 
            returnData.AddInsertInvoiceRow("ERROR", ex.Message); 
            break; 
           } 
           returnData.AddInsertInvoiceRow(row); 
          } 
         } 

        con.Close(); 
        cmd.Dispose(); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      Log.Error(ex); 
      returnData.AddInsertInvoiceRow("ERROR", ex.Message); 
     } 

     return returnData; 
    } 
+0

Vielleicht könnten Sie die tatsächliche Fehlermeldung teilen? Auch der gespeicherte Prozedurcode. Sonst werden wir raten und es könnte alles sein. –

+0

Wenn es einen Fehler auf dem SP gibt, wird eine Tabelle mit ID und Fehler Beschreibung zurückgegeben, die ich hier abrufen: results ["Value_log"]. ToString(); Nachdem 400 Datensätze mit 2 Threads ausgeführt wurden, geben Sie ein vollständig anderes XML-Dataset mit den SP-Einfügeparametern und ihren Werten zurück: Tipo, Cajero, TermId usw. Es ist seltsam, dass nicht nur die aktuelle Transaktion, sondern alle vorherigen zurückgegeben werden 400 Transaktionen, die zuvor eingefügt wurden. Der Fehler ist also eine CastException, kann Value_log nicht in der Rückgabe finden, die das Programm von der SP Datatable erwartet. –

Antwort

1

Sie eine DML-Operation auszuführen, in Ihrem Fall INSERT (von geposteten Code new SqlCommand("InsertInvoice", con)), warum dann ExecuteReader() es sollte eher sein cmd.ExecuteNonQuery()

+0

"InsertInvoice" ist der Name der SQL Stored Procedure, der Grund für die Verwendung von ExecuteReader ist, weil der SP eine DataTable mit Information zurückgibt, die ich in der Methode hier zurückgeben: InsertInvoiceRow row = returnData.NewInsertInvoiceRow(); versuchen Sie { row.TIPO_log = Ergebnisse ["Type_log"]. ToString(); row.VALOR_LOG = Ergebnisse ["Value_log"]. ToString(); } –

Verwandte Themen