在交易中获得SCOPE_IDENTITY

时间:2016-11-16 23:37:10

标签: c# sql-server sql-server-2008 tsql transactions

我有一个相当复杂的对象,包含嵌套的项目列表,每个项目都有自己的表格。

创建此对象时,出于性能原因,我想将其与子项及其所有后代一起插入到单个事务中。

我的桌子:

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...

我这样做的方法是将所有查询存储到'operation'对象中,然后在事务中循环遍历它们。

 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();
            }
        }

我的问题是我似乎无法找到一种方法将SELECT SCOPE_IDENTITY()存储到一个变量(类似于这个:“SELECT SCOPE_IDENTITY()into @ChildId;”)以便在以后的命令中使用(但在同一个命令中)交易)。

2 个答案:

答案 0 :(得分:0)

您可以始终使用OUTPUT子句代替SCOPE_IDENTITY函数。这是一种更加强大和灵活的方法。

declare @id TABLE(id int not null);
INSERT INTO Child(mycolumns, parentid) 
OUTPUT INSERTED.childid INTO @ID(id)
VALUES (mydata, @ParentId);

增加的优点是您可以将多个ID存储到表变量中。例如,您可以将ParentID存储在ChildID旁边:

declare @id TABLE(ParentId int not null, ChildID int not null);
INSERT INTO Child(mycolumns, parentid) 
OUTPUT INSERTED.parentid, INSERTED.childid INTO @ID(ParentID, ChildID)
VALUES (mydata, @ParentId);

答案 1 :(得分:0)

首先,当只有一个表时,不需要三个表。

id parentid
1  null
2  1
3  2

在您当前的场景中,如果可以批量插入(多个插入),那么您应该使用OUTPUT子句。

您的完整代码不可见,但我认为,您需要返回输出参数再次传递它。