SqlDataReader .RecordsAffected неправильно возвращает -1 при использовании INSERT …OUTPUT.inserted

#c# #sql-server-2008 #ado.net

#c# #sql-server-2008 #ado.net

Вопрос:

Мы полагаемся на SqlDataReader.RecordsAffected подсчет количества строк, измененных хранимой процедурой.

MSDN указывает его определение как:

Количество измененных, вставленных или удаленных строк; 0, если ни одна строка не была затронута или оператор не удался; и -1 для операторов SELECT … Значение этого свойства является кумулятивным. Например, если две записи вставлены в пакетном режиме, значение RecordsAffected будет равно двум.

Похоже, что ADO.NET неверно интерпретирует любой оператор, использующий OUTPUT предложение как SELECT оператор, и возвращает -1 RecordsAffected вместо фактического количества измененных строк.

Например:

 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 параметров в наших хранимых процедурах.

Ответ №1:

Что ж, это, безусловно, помогает обратить пристальное внимание на документацию.

Опять же, из MSDN:

Свойство RecordsAffected не устанавливается до тех пор, пока не будут прочитаны все строки и вы не закроете SqlDataReader .

Это в некотором роде ложь.

RecordsAffected устанавливается перед закрытием SqlDataReader , но не все время. Мы запрашивали его перед закрытием объекта, и это всегда работало нормально — пока мы не начали использовать OUTPUT inserted в нашем T-SQL.

Запрос RecordsAffected после закрытия SqlDataReader выдает правильное измененное количество строк с OUTPUT предложением или без него.