简单 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 时,它将报告更改的行而不是找到的行。
我正在维护一项 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 时,它将报告更改的行而不是找到的行。