2010-03-31 26 views
14

Mein aktuelles Projekt besteht aus 3 Standardschichten: Daten, Geschäft und Präsentation. Ich möchte Dateneinheiten für alle meine Datenzugriffsanforderungen verwenden. Ein Teil der Funktionalität der App wird sein, dass es alle Daten innerhalb einer flachen Datei in eine Datenbank kopieren muss. Die Datei ist nicht so groß, so dass ich SqlBulkCopy verwenden kann. Ich habe mehrere Artikel über die Verwendung der SqlBulkCopy-Klasse in .NET gefunden. Alle Artikel verwenden jedoch DataTables, um Daten hin und her zu verschieben.SqlBulkCopy und Entity Framework

Gibt es eine Möglichkeit, Datenelemente zusammen mit SqlBulkCopy zu verwenden, oder muss ich DataTables verwenden?

Antwort

1

Sie können einen Datensatz als Serialisierung der Datenentität betrachten. Im Allgemeinen denke ich, SqlBulkCopy ist eine Tabelle zu Tabelle Sache, daher der Grund für Databases.

1

SqlBulkCopy verwendet einen IDataReader beim Aufrufen der WriteToServer-Methode, sodass Sie IDataReader basierend auf einer Sammlung, die IEnumerable ist, implementieren können. Dadurch können Sie einen Entitätssatz aufnehmen und SqlBulkCopy mithilfe Ihrer IDataReader-Implementierung aufrufen.

19

Sie müssen die Entitäten in einen IDataReader oder DataTable konvertieren.

Es gibt eine kleine Hilfsklasse mit zu unterstützen, entwickelt mit: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389

EDIT: Msdn Link gebrochen ist, kann alt Kopie hier: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

Dann können Sie SqlBulkCopy verwenden wie folgt:

var sbCopy= new SqlBulkCopy(connectionString); 
sbCopy.DestinationTableName = "TableName"; 
sbCopy.WriteToServer(entitiesList.AsDataReader()); 
+0

The Link installiert werden gebrochen –

+2

@JonBarker - Hier ist der GitHub-Link: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – DaveHogan

+0

@DaveHogan Ich mag die Idee, die Sie hier haben. Wir säen 200.000 plus Artikel und es ist schmerzhaft, um es gelinde auszudrücken. Ich habe versucht, es in unsere Repo-EF-Seeding zu ziehen, aber beim Erstellen eines Office-Elements, das ein Child-Objekt von say Address hat, würde es die untergeordneten Elemente oder die Relation Ship nicht erstellen. Ist dies möglich oder über den Rahmen des Codes hinaus? Danke – Jon

5

Wir haben versucht, und ein paar Ansätze getestet beim Einfügen von Bulk-EF mit und gingen schließlich mit Tabellenwertparameter für das erhalten th Die beste Leistung bei einer Reihe von Reihengrößen. Ich habe die Nummern nicht zur Hand, aber ich weiß, dass Performance of bcp/BULK INSERT vs. Table-Valued Parameters ein leitender Faktor war.

Wir verwendeten ursprünglich SqlBulkCopy gekoppelt mit einem Adapter, der eine IEnumerable<T> nahm und eine IDataReader erstellt. Außerdem wurden die relevanten Metadaten für SqlBulkCopy generiert. Vorteil hier war, dass der Import ein Code-Ding ist. Der Code, den @davehogan gepostet hat, wurde als Grundlage dafür verwendet.

Tabellenwertparameter erfordern eine gespeicherte Prozedur und einen in der Datenbank definierten Tabellentyp. Wenn Sie Code zuerst verwenden, können Sie SQL ausführen, um diese als Teil Ihres Erstellungsskripts zu erstellen. Während dies mehr Arbeit ist, haben wir festgestellt, dass wir einen wesentlich konsistenteren und schnelleren Durchsatz von Zeilen in die Datenbank haben.

Es ist auch eine Überlegung wert nicht Masseneinfügung in Ihre Haupttabelle. Wir verwenden eine temporäre Heap-Tabelle und fügen einen gruppierten Index hinzu, sobald die Daten importiert wurden. Wir führen dann eine MERGE zwischen der temporären Tabelle und der Haupttabelle durch. Dies hat den Vorteil, dass der Index der Haupttabelle während des Einfügens nicht gesperrt wird und die Nebenläufigkeit verbessert wird. Mit dieser Methode erreichen wir pro CPU durchschnittlich 2500 Zeilen pro Sekunde.

Lassen Sie mich wissen, wenn Sie weitere Informationen wünschen.

0

SqlBulkCopy ist eine direkte, fast bytearrayartige Übertragung von Zeilendaten vom Client zum SQL Server. Es ist leicht der effizienteste Weg, um Daten in SQL Server zu bekommen.

Seine Leistung liegt jedoch in wirklich "Massen" -Operationen. Hunderte oder Tausende von Zeilen sind nicht unbedingt hoch genug, um die Verwendung zu rechtfertigen.Zehntausende bis Millionen von Reihen sind, wo die Leistung von SqlBulkCopy wirklich erstrahlen wird. Und am Ende reden wir nur über die Daten zum Server.

Es gibt noch andere wichtige Herausforderungen beim Abrufen einer Reihe von Zeilen in eine Tabelle der Produktionsdatenbank. Reindexing, Neuordnung (wenn es einen gruppierten Index gibt), Fremdschlüsselvalidierung, all diese Dinge fügen Ihrer Einfügung Zeit hinzu und sind potentiell Tabellen- und Indexsperrung.

Außerdem werden TVP-Daten auf die Festplatte geschrieben (als temporäre Tabellendaten) und können dann in Ihre Tabellen eingegeben werden. SqlBulkCopy ist in der Lage, direkt an Ihren Tisch zu gehen ... die Leistung ist in diesem Fall wesentlich schneller, jedoch muss die Geschwindigkeit für die Parallelität ausgeglichen werden.

Ich denke, die allgemeine Regel ist, wenn Sie eine Handvoll Zeilen zu behandeln haben, denken TVPs, und wenn Sie viele tausend Zeilen haben, erwägen Sie, es zu SQL Server so schnell wie möglich über SqlBulkCopy.

-2

Als Ergänzung zu @DaveHogan Antwort,

Es jetzt neue Bibliotheken, die Bulk Insert ermöglichen die Durchführung für Entity Framework mit Dateneinheiten anstelle von Datatable (SqlBulkCopy unter der Haube verwendet wird).

Haftungsausschluss: Ich bin der Besitzer des Projekts Entity Framework Extensions

Diese Bibliothek ist nicht kostenlos, sondern erlaubt auf einfache Weise auszuführen:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

Unter der Haube wird SqlBulkCopy verwendet. Die Verwendung der Erweiterungsmethode make ist wesentlich einfacher/schneller als das Codieren einer benutzerdefinierten Lösung für jeden zu verwendenden Bulk-Insert.

Beispiel

// Easy to use 
context.BulkSaveChanges(); 

// Easy to customize 
context.BulkSaveChanges(bulk => bulk.BatchSize = 100); 

schlechte Leistung

Es tut mir leid Sie schlechte Leistung,

Achten Sie darauf, von einem gemeinsamen Fehler nicht Zeit einschließlich bekommen wie zu vergessen JIT Kompilieren, indem Sie Add anstelle von AddRange verwenden, was sich auf die Testleistung auswirkt, aber nicht mit unserer Bibliothek zusammenhängt.

Die meisten Benutzer berichten von einer 25- bis 50-fachen Leistungsverbesserung, wenn sie alle üblichen Leistungsbenchmarkfehler ausschließen.

Siehe: Entity Framework Extensions - Benchmark

+0

schlechte Leistung –

+0

Hello @Ashraf, lassen Sie uns bitte warum Du sagst schlechte Leistung. Es wird normalerweise durch einen allgemeinen Fehler verursacht, der nicht mit unserer Bibliothek zusammenhängt, wie die Verwendung von Add over AddRange –

+1

. Sorry, mein Fehler. Wir müssen den Tracking-Cache deaktivieren. –

1

Sie Bulk package Bibliothek verwenden. Bulk Insert 1.0.0 Version wird in Projekten mit Entity Framework> = 6.0.0 verwendet. Weitere Beschreibung finden Sie im unten Link- Bulkoperation source code