У меня есть довольно сложный объект, содержащий вложенные списки элементов, каждый из которых имеет свою собственную таблицу.Получить SCOPE_IDENTITY mid-transaction
При создании этого объекта я хотел бы вставить его вместе с его дочерними элементами и всеми их потомками в одну транзакцию по причине производительности.
мои таблицы:
Parent
|Id| Has a list of child
Child
|Id|ParentId| Has a list of Grandchild
Grandchild
|Id|ChildId|
Вот что моя сделка будет выглядеть следующим образом:
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...
То, как я сделать это, сохраняя все свои запросы в «операции» объект, а затем пересекая их в транзакцию.
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();
}
}
моя проблема я не могу показаться, чтобы найти способ сохранить выбор SCOPE_IDENTITY() в переменную (что-то похожее на это: «SELECT SCOPE_IDENTITY() в @ChildId;») для использования в последующей команде (но в той же транзакции).
Быстрое сканирование..Modify 'command.ExecuteNonQuery();' затем объявить и использовать 'insertId = (int) command.ExecuteScalar();' для получения нового идентификатора, который вам нужно передать как 'parameter' для следующей операции. – Searching
Совсем другой вариант - вставить все строки для одного поколения в один «INSERT» с помощью ['OUTPUT'] (https://msdn.microsoft.com/en-us/library/ ms177564.aspx), чтобы получить значения столбца идентификатора для вновь вставленных строк (и другого уникального столбца) во временную таблицу. ('OUTPUT' может использоваться с' INSERT', 'UPDATE',' DELETE' и 'MERGE' и обеспечивает доступ к значениям _before_ и _after_ в случае' UPDATE'.) Повторите для каждого поколения, присоединяясь к новым строкам с предками по уникальной ценности. Сложите все это в одну команду и дайте базе данных обработать все остальное. – HABO
Я закончил тем, что сказал @Searching. Я создал другой метод, который заменил отсутствующие значения parentid/childid в моих запросах после выполнения команды. ExecuteScalar(). благодаря! – brem