简单 SqlCommand.ExecuteNonQuery 即使没有更新数据库也总是返回 1

Simple SqlCommand.ExecuteNonQuery always returning 1 even when it didn't update database

我正在维护一项 Windows 服务,最近 updated/compiled 在 .Net 4.5 中,放置在 Server 2012 上,并使用相同的 SQL Server 2008 数据库 运行 在更新之前。我们 运行 遇到了一个问题,它正在使用一个简单的 SQL 语句更新数据库,这显然在更新之前一直有效。现在更新几乎总是有效,但是一旦(也许?)一千次更新它 "fools" 我们和 ExecuteNonQuery returns 一个 1 表示它更新了行,但实际上没有。

如果您想告诉我代码有什么问题,请继续。我真正希望的是关于处理更新的更 "fool" 证明方法的建议。也许将连接设置为使用 t运行sactions 会更好?也许使用存储过程并在存储过程中执行 t运行sactions 会好得多?多少钱better/Why?

代码很简单(太简单了?):

try
{
    string sql = "UPDATE table SET barcode = '" + newBarcode + "' WHERE pk = '" + reportId + "'"; // no semicolon in the SQL
    SqlCommand command = new SqlCommand(sql, connection); // connection recently opened

    rowsUpdated = command.ExecuteNonQuery();

    if (rowsUpdated != 1)
    {
        connection.Close()
        throw new Exception("...");
    }
    else
    ...
    connection.Close();
}
catch (Exception ex)
... // general exceptions handled
finally
... // make sure connection is closed

我知道外部影响有可能(尽管不太可能)在更新后使该字段无效。如果这可能是唯一的可能性,请发表评论。

将行更新为相同值的更新仍算作受影响的行。

将其与以下内容进行比较:

UPDATE table SET barcode = @x WHERE pk = @id AND barcode <> @x

如果更新为"do nothing",显式守卫将跳过这一行,因此它将算作如果不需要更改,则更改。


虽然 应该 使用占位符(和 using 语句),但这些都不会改变更新语句的结果。

正如其他答案中所建议的那样,使用参数化查询以及使用 using 语句来初始化连接,这样您就不必负责在完成后关闭它。

同时使用和输出参数以及@@ROWCOUNT 函数来查看是否有任何行已更新。

使用 RowsAffected 变量做进一步处理。

using (SqlConnection conn = new SqlConnection("Connection string here..."))
{
  string sqlcmd = "UPDATE table SET barcode = @newBarcode WHERE pk =  @reportId  SET @RowCount = @@ROWCOUNT;";

    conn.Open();
    SqlCommand cmd = new SqlCommand(sqlcmd, conn);

    cmd.Parameters.Add("@RowCount", SqlDbType.Int).Direction = ParameterDirection.Output;
    cmd.Parameters.Add(new SqlParameter("@newBarcode", newBarcode));
    cmd.Parameters.Add(new SqlParameter("@reportId", reportId));

    rowsUpdated = cmd.ExecuteNonQuery();
    int RowsAffected = Convert.ToInt32(cmd.Parameters["@RowCount"].Value);

   if (RowsAffected == 0)
    {
      throw new Exception("...");
     }
   else
    ......
 }

UPDATE 查询中 ExecuteNonQuery 的 return 值是更新语句的 where 子句匹配的行数,而不是实际更新的行数。

您应该使用连接字符串选项 'use affected rows'。当设置为 true 时,它​​将报告更改的行而不是找到的行。

请参考https://bugs.mysql.com/bug.php?id=44194