2016-05-12 5 views
1

Ich bin hier ein bisschen fest hier versuchen viele Daten (eine Million Datensätze insgesamt) aus drei verwandten Tabellen zu anderen drei verwandten Tabellen in der gleichen Datenbank zu kopieren.Verwenden von SqlBulkCopy in einer Transaktion für mehrere, verknüpfte Tabellen

Mein Tischdesign ist wie folgt:

enter image description here

Was ich brauche, ist in der Lage sein, Daten aus dem Entwurf Tabellen kopieren über die nicht-Entwurf Tabellen in einer Transaktion, die ich in der Lage bin zu Rollback, wenn etwas schief geht. Dies wird benötigt, da wir keine Billing und BillingPriceLine Datensätze in der Datenbank haben wollen, wenn die Bulk-Einfügung von BillingPriceLineSpecificationDraft Kopie fehlgeschlagen ist.

Da ich jedoch SqlBulkCopy zum Kopieren der Datensätze verwende, kann ich die neuen IDs nicht erfassen, um die richtigen Beziehungen zwischen den drei neuen Tabellen herzustellen. Wenn ich einen Lesevorgang, d. H. Die Billing Tabelle in der Transaktion, um die richtige Billing ID zu erhalten, bekomme ich eine Auszeit, die erwartet wird, da die Tabellen innerhalb der Transaktion gesperrt sind.

Ich habe versucht, die IsolationLevel Enum auf die Transaktion (in der Tat, ich ging verrückt und versuchte sie alle ;-)), aber sie taten nichts, was es scheint.

Gibt es einen guten Weg, dies zu tun, dass ich vermisse?

Vielen Dank im Voraus.

Antwort

3

Sie können das nicht wirklich mit Bulk-Kopie tun.

Sie müssen auch nicht - es ist eine sehr schlechte Praxis, echte Tabellen mit SqlBulkCopy zu berühren, denn wer auch immer dieses Ding geschrieben hat, hat kein Verständnis für SQL Server-Sperrmechanismen.

  • Erstellen Sie 3 temporäre Tabellen mit der gleichen Tabellenstruktur wie das Ziel.
  • SqlBulkCopy in diese Tabellen (wodurch vermieden SqlBulkCopy Sperren Verschrauben Sie und Vermeidung der Transaktion Problem).
  • Geben Sie dann in einer Transaktion 3 INSERT INTO-Anweisungen mit den Daten aus den temporären Tabellen als Quelle aus.

Ergebnis ist das Beste aus beiden Welten. Sobald Sie die Daten in den temporären Tabellen (mit möglicherweise gefälschten IDs) haben, können Sie einige wirklich interessante SQL ziehen, um die Quellentabelle in einer Transaktion mit den relevanten internen IDs für die nächste Tabelle zu aktualisieren. Das SQL wird komplex, aber das ist das Beste, was Sie tun können.


Erklärung, warum SqlBulkCopy schlecht ist:

SqlBulkCopy wirklich sehr problematisch ist - es Schraubverriegelung der Fall ist. Es erfordert eine exklusive Tabellensperre (was "sort of ok" ist). Es fragt danach - aber es wartet nie (d. H. Wenn es eine Sperre für den Tisch gibt, schlägt dies fehl), dann versucht es erneut .... nach einiger Zeit .... bis ein Timeout abläuft. Das Ergebnis ist, dass es auf einer Tabelle mit Aktivität wirklich schwierig ist, SqlBulkCopy zu erhalten, um eine Sperre zu erhalten. Der richtige Code wäre, auf die exklusive Sperre zu warten ... nun.

+0

Hallo TomTom, vielen Dank für deine Antwort, es macht Sinn :-) Ich kann erfolgreich Bulk einfügen in die drei temporären Tabellen, aber ich bin ein bisschen in einem Verlust, wenn es um den Einsatz kommt Anweisungen, da die "BillingPriceLine" mit dem Datensatz "Abrechnung" und vica verca in Zusammenhang stehen sollte. Hast du irgendwo ein Beispiel, das zeigt, wie man diese Einsätze macht? :-) Danke noch einmal! – bomortensen

+0

Nein, nicht als Beispiel. Ich mache Tonnen von Beilagen, aber ich habe in den meisten Fällen natürliche Schlüssel. Denken Sie daran: Sie können der temporären Tabelle ein weiteres Feld mit gefälschten IDs hinzufügen, die Sie auf der Clientseite generieren. Benutze sie dann für die Joins. Das ist nicht so kompliziert - aber es ist "echt" sql, nicht die Quiz-Sachen, die die meisten Leute heutzutage machen. – TomTom

+0

Hallo TomTom, ich verstehe, was du sagst :-) Ich habe es geschafft, indem ich die 'OUTPUT'-MSSQL-Klausel benutzte, um sowohl die ID des Entwurfs als auch die eingefügte ID zu speichern und die Beziehungen auf diese Weise zu erstellen. Funktioniert perfekt. Danke für Ihre Hilfe! – bomortensen