2016-11-16 63 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要返回輸出參數以再次傳遞它。