Ich habe ein ziemlich komplexes Objekt, das verschachtelte Listen von Elementen enthält, jedes von ihnen mit einer eigenen Tabelle.Get SCOPE_IDENTITY Mitte der Transaktion
Wenn ich dieses Objekt erstelle, möchte ich es aus Leistungsgründen zusammen mit seinen Kindern und allen ihren Nachkommen in einer einzigen Transaktion einfügen.
meine Tabellen:
Parent
|Id| Has a list of child
Child
|Id|ParentId| Has a list of Grandchild
Grandchild
|Id|ChildId|
Hier ist, was meine Transaktion aussehen würde:
INSERT INTO Parent(mycolumns) VALUES (mydata);SELECT SCOPE_IDENTITY() into @ParentId;
--insert the first child and his grandchilds
INSERT INTO Child(mycolumns, parentid) VALUES (mydata, @ParentId);SELECT SCOPE_IDENTITY() into @ChildId;
INSERT into Grandchild(mycolumns, childid) VALUES (mydata, @ChildId);
INSERT into Grandchild(mycolumns, childid) VALUES (mydata, @ChildId);
... loop through all grandchilds with this childid
--insert the second child and his grandchilds
INSERT INTO Child(mycolumns, parentid) VALUES (mydata, @ParentId);SELECT SCOPE_IDENTITY() into @ChildId;
INSERT into Grandchild(mycolumns, childid) VALUES (mydata, @ChildId);
INSERT into Grandchild(mycolumns, childid) VALUES (mydata, @ChildId);
... loop through all grandchild with this childid again...
Die Art, wie ich dies durch die Speicherung aller meiner Abfragen in eine ‚Operation‘ Objekt ist zu tun, und dann Durchlaufen sie in einer Transaktion.
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
foreach (var operation in operations)
{
using (SqlCommand command = new SqlCommand(operation.SqlCommand, connection, transaction))
{
if (operation.Parameters != null)
{
foreach (var param in operation.Parameters)
{
command.Parameters.AddWithValue(param.Name, param.Value);
}
}
command.ExecuteNonQuery();
}
}
transaction.Commit();
}
}
mein Problem ist, ich kann nicht scheinen, einen Weg zu finden SELECT SCOPE_IDENTITY zu speichern() in eine Variable (so etwas wie folgt aus: "SELECT SCOPE_IDENTITY() in @ChildId;") in einem späteren Befehl zu verwenden (aber in der gleichen Transaktion).
Ein kurzer Scan..Modify 'command.ExecuteNonQuery();' deklarieren Sie dann und verwenden Sie 'insertId = (int) command.ExecuteScalar();', um die neue ID zu erhalten, die Sie als 'Parameter' übergeben müssen für die nächste Operation .. – Searching
Eine ganz andere Möglichkeit ist es, alle Zeilen für eine Generation in einem einzigen 'INSERT' mit einem [' OUTPUT' einzufügen (https://msdn.microsoft.com/en-us/library/ ms177564.aspx) -Klausel zum Abrufen der Identitätsspaltenwerte für neu eingefügte Zeilen (und eine weitere eindeutige Spalte) in eine temporäre Tabelle. ('OUTPUT' kann mit' INSERT', 'UPDATE',' DELETE' und 'MERGE' verwendet werden und bietet Zugriff auf _before_ und _after_ Werte im Falle von 'UPDATE'.) Wiederholen Sie dies für jede Generation, indem Sie die neuen Zeilen verbinden mit den Vorfahren auf dem einzigartigen Wert. Staple alles in einen Befehl und lass die Datenbank den Rest erledigen. – HABO
Ich endete damit, was @Searching sagte. Ich habe eine andere Methode erstellt, die die fehlenden Werte für parentid/childid in meinen Abfragen nach dem Ausführen von command.ExecuteScalar() ersetzt hat. Vielen Dank! – brem