用FK将事务插入到第一行创建的行中

问题描述:

我有一批需要在单个事务中插入的行,第一行是标题,所有后续行必须引用第一行。用FK将事务插入到第一行创建的行中

这是我正在试图插入的第一行:

using (var connection = new SqlConnection(_connectionString)) 
{ 
    connection.Open(); 
    var transaction = connection.BeginTransaction(); 

    try 
    { 
     // create the record header 
     using (var createRecordCommand = connection.CreateCommand()) 
     { 
      createRecordCommand.CommandText = 
       "DECLARE @RecordId INT;" + 
       $"INSERT INTO ..." + 
       "SET @RecordId = scope_identity();"; 

      createRecordCommand.Transaction = transaction; 
      createRecordCommand.ExecuteNonQuery(); 

我挣扎引用的recordId在随后的声明,似乎觉得变量@RecordId没有在下面的代码片段声明。 '必须声明标量变量“@RecordId”。'

using (var createAttributeCommand = connection.CreateCommand()) 
{ 
    createAttributeCommand.Transaction = transaction; 

    createAttributeCommand.CommandText = 
     $"INSERT INTO ... (RecordId,...) VALUES (@RecordId,...)"; 

而且提取作为一个参数被证明是困难@RecordId变量,它不喜欢它,当我用下面的线结合DECLARE @RecordId INT;

createRecordCommand.Parameters.Add(new SqlParameter("@RecordId", SqlDbType.Int) { Direction = ParameterDirection.Output }); 
+1

你为什么不把你的逻辑放到一个存储过程,然后就调用从C#程序? –

+0

我已经削减了问题的复杂性,我们试图实现的过程对于存储过程而言非常复杂,不幸的是。 –

+1

嗯,是什么?存储过程过于复杂?将插入作为存储过程执行,并使用OUTPUT参数返回标识。 –

我没有意识到你可以在事务提交之前提取数据,假设由于ExecuteScalar()不起作用,我会遇到同样的问题。

正如评论中指出的那样,存储过程可能是最好的解决方案,SQL专家在一段时间后听起来像破碎的记录; p。由于存在可变参数数量,因此短期而言这将过于复杂,验证和值将根据业务逻辑进行变异。作为一个团队,我们在C#中更加舒适,因此逻辑将一直保持到完全确定下来。

结果代码如下,N.B.在实际的代码,通过所有变量作为参数,以避免SQL注入,我们到了,这是演示仅

using (var connection = new SqlConnection(_connectionString)) 
{ 
    connection.Open(); 
    var transaction = connection.BeginTransaction(); 

    try 
    { 
     // create the record header 
     using (var createRecordCommand = connection.CreateCommand()) 
     { 
      createRecordCommand.CommandText = 
       //"DECLARE @RecordId INT;" + 
       $"INSERT INTO ..." + 
       "SET @RecordId = scope_identity();"; 

      createRecordCommand.Transaction = transaction; 
      createRecordCommand.Parameters.Add(new SqlParameter("@RecordId", SqlDbType.Int) { Direction = ParameterDirection.Output }); 
      createRecordCommand.ExecuteNonQuery(); 

      recordId = (int) createRecordCommand.Parameters["@RecordId"].Value; 

// ... 

using (var createAttributeCommand = connection.CreateCommand()) 
{ 
    createAttributeCommand.Transaction = transaction; 
    createAttributeCommand.CommandText = 
     $"INSERT INTO ... (RecordId,...) VALUES ({recordId},...)"; 

// ... 

transaction.Commit();