2016-11-16 56 views
0

我有一个相当复杂的对象,包含项目的嵌套列表,每个项目都有自己的表格。获取SCOPE_IDENTITY中间交易

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

我的表:

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

我的问题是我不能似乎找到一种方法来存储SELECT SCOPE_IDENTITY()为变量(一个类似于此:“选择SCOPE_IDENTITY()到@ChildId;”)在以后的命令中使用(但在同一笔交易中)。

+0

快速扫描..修改'command.ExecuteNonQuery();'然后声明并使用'insertId =(int)command.ExecuteScalar();'得到新的Id,你需要传递'parameter'用于下一个操作.. – Searching

+0

一个完全不同的选择是将一代中的所有行插入到带有['OUTPUT']的单个INSERT'中(https://msdn.microsoft.com/zh-cn/library/ ms177564.aspx)子句将新插入的行(和另一个唯一列)的标识列值获取到临时表中。 ('OUTPUT'可以与'INSERT','UPDATE','DELETE'和'MERGE'一起使用,并且在'UPDATE'的情况下可以访问_before_和_after_值。)对每一代重复,加入新行与祖先的独特价值。把它全部放到一个命令中,让数据库处理其余的部分。 – HABO

+0

我最终做了什么@搜索说。我创建了另一种方法,在执行command.ExecuteScalar()后,在查询中替换了丢失的parentid/childid值。谢谢! – brem

回答

0

除了SCOPE_IDENTITY函数,您始终可以使用OUTPUT子句。这是一个更加健壮和灵活的方法。

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); 
0

首先,当只有一个表执行操作时,不需要三个表。

id parentid 
1 null 
2 1 
3 2 

在你目前之情况,如果有可以批量插入(超过一个刀片)则是你应该使用OUTPUT子句。

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