使用 INSERT...OUTPUT.inserted 时,SqlDataReader.RecordsAffected 错误地返回 -1

发布于 2024-12-08 18:18:42 字数 1060 浏览 0 评论 0原文

我们依赖 SqlDataReader.RecordsAffected来计算存储过程修改的行数。

MSDN 对其定义如下:

更改、插入或删除的行数;如果没有行受到影响或者语句失败,则为 0; SELECT 语句为 -1...该属性的值是累积的。例如,如果批量插入两条记录,则RecordsAffected的值为2。

看来 ADO.NET 会误解任何使用 OUTPUT 的语句子句作为SELECT语句,并为RecordsAffected返回-1,而不是实际修改的行数。

例如:

CREATE TABLE dbo.example (
      a INT
    , b VARCHAR(10)
    , c DATETIME2(3)    DEFAULT(SYSUTCDATETIME())
);

INSERT INTO dbo.example (
     a
   , b
)
OUTPUT inserted.c -- Comment out this line and RecordsAffected goes from -1 to 1.
VALUES (
     1
   , 'blah'
);

ADO.NET 的这种行为是有意为之还是错误造成的?

作为记录,我们计划更改代码以使用 @@ROWCOUNT 显式捕获已修改行的计数,并将它们作为存储过程中的 OUTPUT 参数返回。

We rely on SqlDataReader.RecordsAffected to count the number of rows modified by a stored procedure.

MSDN states its definition as:

The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements... The value of this property is cumulative. For example, if two records are inserted in batch mode, the value of RecordsAffected will be two.

It appears that ADO.NET misinterprets any statement using the OUTPUT clause as a SELECT statement and returns -1 for RecordsAffected instead of the actual count of modified rows.

For example:

CREATE TABLE dbo.example (
      a INT
    , b VARCHAR(10)
    , c DATETIME2(3)    DEFAULT(SYSUTCDATETIME())
);

INSERT INTO dbo.example (
     a
   , b
)
OUTPUT inserted.c -- Comment out this line and RecordsAffected goes from -1 to 1.
VALUES (
     1
   , 'blah'
);

Is this ADO.NET behavior by design or by error?

For the record, we plan to change our code to explicitly capture counts of modified rows using @@ROWCOUNT and return them as OUTPUT parameters in our stored procedures.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拿命拼未来 2024-12-15 18:18:42

嗯,密切关注文档肯定会有所帮助。

再次,来自 MSDN

在读取所有行并关闭 SqlDataReader

这有点谎言。

RecordsAffected 在关闭 SqlDataReader 之前设置,但并非始终如此。我们在关闭对象之前查询它,并且一直工作得很好——直到我们开始在 T-SQL 中使用OUTPUT insert

关闭 SqlDataReader 后查询 RecordsAffected 会产生正确的修改行计数,无论是否带有 OUTPUT 子句。

Well, it certainly helps to pay close attention to the documentation.

Again, from MSDN:

The RecordsAffected property is not set until all rows are read and you close the SqlDataReader.

This is somewhat of a lie.

RecordsAffected is set before you close SqlDataReader, but not all the time. We were querying it before closing the object and that always worked fine--until we starting using OUTPUT inserted in our T-SQL.

Querying RecordsAffected after closing your SqlDataReader yields the correct modified row count, with or without the OUTPUT clause.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文