多语句SQL事务在null参数处失败

时间:2012-12-28 07:33:33

标签: c# sql-server tsql transactions

我有一个多语句SQL查询,它发生在SqlTransaction中,如下所示:

string sName = "";
string sNumber = "";
string sFirstName = "";

string sqlQuery1 = @"INSERT INTO myTable(Name, Number) VALUES (@_Name, @_Number)";
string sqlQuery2 = @"INSERT INTO myOtherTable( ID, FirstName) VALUES ( @_ID, @_First )";

SqlConnection conn = new SqlConn(***);
conn.Open();
SqlTransaction transaction;

SqlCommand command1 = new SqlCommand(sqlQuery1, conn, transaction);
SqlCommand command2 = new SqlCommand(sqlQuery2, conn, transaction);

command1.Parameters.Add("@_Name", SqlDbType.NVarChar, 255).Value = sName;
command1.Parameters.Add("@_Number", SqlDbType.NVarChar, 255).Value = sNumber;

int? returnedID = (int?)command1.ExecuteScalar();

command2.Parameters.Add("@_ID", SqlDbType.Int).Value = (int)returnedID;  <--- Error
command2.Parameters.Add("@_First", SqlDbType.NVarChar, 255).Value = sFirstName;

command2.ExecuteNonQuery();

transaction.Commit();

在我标记为错误的行中,我在执行期间遇到错误“参数化查询需要未提供的参数@_ID。

现在,假设我在将代码简化为此示例时没有拼写错误,为什么我在returnID中为正确执行的语句接收空值?当我在查询中单独运行语句时,我没有错误,它返回成功。为什么在此事务中运行它时为null?谢谢!

编辑:由于这与我所拥有的问题无关,所以我故意暂停了这个问题。否则,我只是忘记了在插入查询中需要的IDENTITY_SCOPE(),因为否则将没有返回值。

3 个答案:

答案 0 :(得分:3)

ExecuteScalar返回查询返回的结果集中第一行的第一列(MSDN)。您的语句是一个插入,它不会返回任何结果集。

修复示例的最简单方法是在一个命令中运行所有查询,并使用SCOPE_IDENTITY获取插入的ID。

string sqlQuery =
    @"INSERT INTO myTable(Name, Number) VALUES (@_Name, @_Number);
      INSERT INTO myOtherTable( ID, FirstName) VALUES ( SCOPE_IDENTITY(), @_First )";

答案 1 :(得分:0)

由于insert语句不返回值,ExecuteScalar()无法根据需要返回标识。您可以将insertselect scope_identity()合并到ExecuteScalar()文档的example中,以获得我认为您期望的功能。

答案 2 :(得分:0)

您似乎假设INSERT INTO myTable(Name, Number) VALUES (@_Name, @_Number)将返回插入行的ID;你为什么那么想?假设是不正确的,这就是为什么你从ExecuteScalar获得一个空值。

如果命令的结果集为空,则

ExecuteScalar返回null,并且INSERT语句的结果集实际上为空,除非您包含OUTPUT子句。