Wie führt dapper mehrmals denselben Befehl aus? Wie ich unten geschrieben habe, füge SQL ein und rufe Dappers Ausführungsmethode mit den Listenparametern auf, also werde ich 3 Objekte einfügen.
Die Frage: Macht dapper 3 Roundtrips zum SQL Server, um 3 Inserts auszuführen, oder sendet er es irgendwie als 1 Roundtrip, um 3 Inserts aufzurufen?
Ich frage mich nur, ob die Verwendung auf diese Weise Vorteile gegenüber nur foreach und dem Aufrufen einer Einfügung nach der anderen hat oder ob es genau dasselbe ist.
Version 1.
var sqlInsert = $"INSERT INTO Book (Id, Title) Values (@Id, @Title)";
var parameters = new List<Book> { new Book("Damian Book", 123), new Book("XXX Book", 156), new Book("Zonk BOok", 167) };
connection.Execute(sqlInsert, parameters);
Version 2.
foreach (var book in parameters)
{
connection.Execute(sqlInsert, book)
}
Ist es Version1 und Version2 doch gleich oder nicht?
Wenn Sie IEnumerable
zum Einfügen mehrerer Elemente an Execute
, wird jedes Element unabhängig eingefügt. Trotzdem gibt es keinen großen Unterschied zwischen den beiden von Ihnen vorgestellten Szenarien.
Dapper erleichtert nur das Einfügen mehrerer Elemente, indem IEnumerable
akzeptiert IEnumerable
. Es implementiert intern nicht so etwas wie Masseneinfügung.
Schauen Sie sich diesen Artikel an:
Dieser Ansatz sendet jedoch jeden Befehl als einzelne, eigenständige Transaktion, was im Fehlerfall zu Inkonsistenzen beim Ausführen einer oder mehrerer Anweisungen führen kann. Die Problemumgehung besteht darin, ein IDBTransaction-Objekt zu verwenden, um eine explizite Transaktion zu erstellen, die alle Ausführungen abdeckt. Leistung und Skalierbarkeit sind schlechter als die Ausführung nur eines Befehls, der ein Array von Objekten übergibt (aufgrund der Netzwerklatenz und damit längerer Transaktionen), aber zumindest die Konsistenz wird garantiert.
Da Dapper jedoch die Tabellenwertparameter von SQL Server und auch JSON unterstützt, empfehle ich, einen dieser Parameter zu verwenden, wenn Sie ein Array von Werten an einen Parameter übergeben müssen. Ich werde in zukünftigen Artikeln darüber diskutieren, also bleiben Sie dran.
Was ist nun, wenn Sie ein Array von beispielsweise 10.000 Werten oder mehr übergeben müssen? Hier ist die richtige Wahl, eine Massenlast zu verwenden, und insbesondere mit SQL Server den Befehl BULK INSERT, der von Dapper leider nicht nativ unterstützt wird. Die Problemumgehung besteht darin, hier nur die reguläre SqlBulkCopy-Klasse zu verwenden, und schon sind Sie fertig.
Alternativ können Sie auch ein Tool wie Dapper Plus - Bulk Insert verwenden .
Weitere Informationen zu Bulk Insert und einem Hack, um dies zu erreichen, finden Sie hier . Dapper unterstützt auch TVPs . Wenn Ihr RDBMS dies tut, verwenden Sie es.
Um Ihren Kommentar zu beantworten:
Wenn ich eine Transaktion erstelle und mehrere Einfügungen darin aufrufe, führt die Transaktion dann einen Roundtrip zur Datenbank durch, um alle aufzurufen? Oder werden Einfügungen immer noch einzeln ausgeführt?
Transaktionen haben nichts mit Masseneinfügung zu tun. Wenn Sie Ihren Codeblock (eine beliebige Version, die Sie in Frage stellen) in eine Transaktion einschließen, ändert sich das Ergebnis nicht. Die gesamte Transaktion wird entweder festgeschrieben oder zurückgesetzt. Ohne Transaktion können Konsistenzprobleme auftreten, wenn der Vorgang irgendwo dazwischen fehlschlägt. Indem Sie Ihren Code in eine Transaktion einschließen, vermeiden Sie dieses Problem einfach. Ihr Kernproblem - Bulk Insert bleibt unverändert.