2017-02-02 1 views
0

Normalerweise werden Sie jeweils ein Update innerhalb einer Schleife durchführen. Wenn Sie 100 Datensätze haben, werden Sie 100 Fahrten zum Server haben, was nicht wünschenswert ist. Wie kann ich eine Gruppe von Datensätzen mit einem einzigen Umlauf in die Datenbank aktualisieren?Was ist der einfachste Weg, um eine Charge von Datensätzen mit nur einer Reise zu aktualisieren?

using System.Data.SqlClient; 

for (int ii = 0; ii < ptList.Length; ii++) { 
    sql = @"update [CCVT].[dbo].[_tb_NCVT_Points] set PointDateTime = CONVERT(datetime, '" 
    + ptList[ii]._dateDt.ToString("yyyy-MM-dd HH:mm:ss.FFF") + "', 121), PointStatus = '" 
    + ptList[ii]._statStr + "', PointValue =" + ptList[ii]._valDoub.ToString() 
    + " WHERE Pointkey = '" + ptList[ii]._pointName + "'; "; 
    theActiveConnection.Open(); 
    SqlCommand cmd = new SqlCommand(sql, theActiveConnection); 
    try { 
     cmd.ExecuteNonQuery(); 
     cmd.Dispose(); 
    } 
    catch (Exception eX) { 
     //handle exceptions 
    } 
} 

Bitte stimmen Sie diese Frage nicht ab.
Die Frage How can I update multiple rows in a table with SQL query? fragte nicht nach einer Reise, und ihre Antwort ergab keine einzige Reise !! Haben Sie gesehen, dass die ExecuteNonQuery-Aktion innerhalb der Schleife ist? Das ist nicht meine Frage und das ist nicht meine Antwort!

foreach (DataGridViewRow row in dataGridView2.Rows) 
    { 
     cm.Parameters["@Qty"].Value = row.Cells[2].Value; 
     cm.Parameters["@Description"].Value = row.Cells[3].Value; 
     cm.Parameters["@Price"].Value = row.Cells[4].Value; 
     cm.ExecuteNonQuery(); 
    } 
    cn.Close(); 
+0

Dann erstellen Sie einfach eine Batch-SQL-Anweisung und führen Sie es in einem Rutsch aus. Oder erstellen Sie eine gespeicherte Prozedur und füttern Sie DataTable mit Ihren Daten. – eocron

+0

Mögliches Duplikat von [Wie kann ich mehrere Zeilen in einer Tabelle mit SQL-Abfrage aktualisieren?] (Http://stackoverflow.com/questions/34341716/how-can-i-update-multiple-rows-in-a-table- with-sql-query) – eocron

+3

Sie können versuchen, das schnellste Verfahren der Welt zu haben, aber wenn Sie das Sicherheitsloch namens Sql Injection nicht beheben, haben Sie ein größeres Problem – Steve

Antwort

3
SqlCommand cmd = new SqlCommand("", theActiveConnection); 
StringBuilder sql = new StringBuilder(); 
for (int ii = 0; ii < ptList.Length; ii++) { 
    sql.AppendLine("UPDATE [CCVT].[dbo].[_tb_NCVT_Points]"); 
    sql.AppendLine($"SET PointDateTime = CONVERT(datetime, @PointDateTime{ii}, 121), PointStatus = @PointStatus{ii}, PointValue = @PointValue{ii}"); 
    sql.AppendLine($"WHERE Pointkey = '@PointKey{ii};"); 
    cmd.Parameters.AddWithValue($"@PointDateTime{ii}",ptList[ii]._dateDt.ToString("yyyy-MM-dd HH:mm:ss.FFF")); 
    cmd.Parameters.AddWithValue($"@PointStatus{ii}",ptList[ii]._statStr); 
    cmd.Parameters.AddWithValue($"@PointValue{ii}",ptList[ii]._valDoub.ToString()); 
    cmd.Parameters.AddWithValue($"@Pointkey{ii}",ptList[ii]._pointName); 

} 
try { 
    cmd.CommandText = sql.ToString(); 
    theActiveConnection.Open(); 
    cmd.ExecuteNonQuery(); 
} 
catch (Exception eX) { 
    //handle exceptions 
} 
finally { 
    cmd.Dispose(); 
    theActiveConnection.Close(); 
} 

Es gibt viele Möglichkeiten, dieses Problem zu behandeln, je nachdem, wie nah und wie unterschiedlich die Befehle sind. In deinem Fall halte ich das für das Beste.

+1

Haben Sie jemals von einer Klasse namens StringBuilder gehört? – Steve

+3

Ich habe, und ich verwende String-Builder, ich habe nur den Code von @JennaLeaf reorganisiert, obwohl es definitiv bessere Möglichkeiten zum Erstellen der Abfrage-Strings gibt. – Andrew

+0

Um dich glücklich @Steve zu machen, habe ich einen String Builder eingebaut. – Andrew

2

Der beste Ergebnis erzielt Weg ist, um Tabellenwertparameter mit einer gespeicherten Prozedur https://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx

Der einfache Weg ist, einfach concat SQL-Anweisungen mit Semikolon mit einem String oder .... Aber beachten Sie, dass dies hat Einschränkungen zu verwenden in der Länge !!!

+0

Ersteres ist besser skalierbar, korrekt? Ich habe auch das Maximum von StringBuilder nachgeschlagen. Ich glaube nicht, dass ich das übertreffen würde. Aber deine frühere Methode ist großartig, ich mag sie! Ich habe es gewählt !!! –

+0

@Jenna: Bitte beachten Sie, dass nicht StringBuilder das Limit, sondern SQL Server ... https://msdn.microsoft.com/de-de/library/ms143432.aspx (die Grenzen sind auch hier sehr hoch) – Markus

1

Warum nicht Dapper - ein einfachen Objekt-Mapper für

.Net
var list = ptList.select(p => new{ 
     DateTime = p._dateDt, 
     Status = p._statStr, 
     Value = p._valDoub, 
     Key = p._pointName 
    }); 
using(var connection = new SqlConnection...) 
{ 
    connection.open() 
    connection.Execute("update [CCVT].[dbo].[_tb_NCVT_Points] set PointDateTime = @DateTime, PointStatus = @Status, PointValue = @Value 
WHERE Pointkey = @Key", list); 
} 
+0

I haven ' Ich habe es noch nicht versucht! Ich benutze Linq und nugget, aber das ist das Projekt meines Kollegen (er ist Anti-linq, Anti-Komplikation), was du dort hingestellt hast, sieht so aus, als müsste es funktionieren! Ich habe es gewählt. Danke. –

2

Die klare Antwort von Andrew geschrieben wurde, aber es hängt davon ab, wo Ihre Daten kommen.

Wenn die Liste der Punkte bereits in der Datenbank ist, und Sie es in eine Liste abfragen (ein SELECT mit einer Schleife, um die Liste zu füllen), dann sollten Sie direkt ein UPDATE durchführen FROM kombiniert SELECT und UPDATE in einer einzigen Anweisung. Eine einzige Reise zum Server, ohne unnötige Zeilen über das Netzwerk.

+0

Ihr arbeitet auch. Wie Sie gesagt haben, ich habe nicht Millionen Update-Stmts, so Andrew ist die Lösung, was ich suche, vor allem, ich nicht lieber eine tmp Arbeitstabelle auf dem Server nur ein paar Hunderte von Aufzeichnungen zu verschmelzen. Für größere Mengen von Updates würde ich definitiv Ihre verwenden. Ich habe deine Antwort gewählt. Siehe auch http://stackoverflow.com/questions/2334712/update-from-select-using-sql-server –

+1

Wenn es bereits in einer Datenbank sicher ist gibt es andere Möglichkeiten, aber selbst dann könnte es einen Grund geben, dass Jenna will Daten durchlaufen ihren Code, Validierung, Anpassungen an den Daten, aber wir wissen nicht, die Quelle der Daten, also habe ich eine Lösung, die immer funktioniert, sobald die Werte sind wo OP ihnen zur Verfügung gestellt. – Andrew

+0

Andrew, die Werte zum Aktualisieren der Datenbankfelder sind NICHT IN DATABASE, sondern wurden von einer Historian-Engine eingegeben. –

Verwandte Themen