【问题标题】:Multi-statement SQL transaction failing at null parameter多语句 SQL 事务在空参数处失败
【发布时间】:2012-12-28 07:33:32
【问题描述】:

我有一个多语句 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。

现在,假设我在将代码简化为这个示例时没有拼写错误,为什么我在返回ID 中收到一个空值以表示正确执行的语句?当我在查询中单独运行该语句时,我没有收到任何错误并且它返回成功。为什么在这个事务中运行它时为空?谢谢!

编辑:我故意放弃了 try{} 捕获,因为它与我的问题无关。否则,我只是忘记了插入查询中需要的 IDENTITY_SCOPE(),否则将没有返回值。

【问题讨论】:

  • 您正在使用 SQLTransaction 对象我建议将代码包装在 try{}catch 中,并且在异常代码中您将需要 transaction.RollBack();如果该交易失败..对于初学者..

标签: c# sql-server tsql transactions


【解决方案1】:

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

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

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

【讨论】:

  • @@IDENTITY 不应该被使用,使用 scope_identity() 会更好。
  • @paritosh,你说得对,@@IDENTITY 可以检索插入不同范围的 id,我会修正我的答案。谢谢
  • 当然,我忘记了添加Scope_Identity()。谢谢!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多