ExecuteNonQuery() и SET NOCOUNT ON
От: KellyLynch  
Дата: 16.04.15 15:12
Оценка: 24 (2)
У меня есть: MS SQL Server 2008 R2
C# приложение – его клиент
Я встретил следующий (причём невоспроизводимый регулярно) баг. Такой вот код на клиенте приносит “количество затронутых строк” большее чем их должно быть на самом деле:

...
Microsoft.Practices.EnterpriseLibrary.Data.Database db = DatabaseFactory.CreateDatabase("XYZ");
...
DbCommand cmd = db.GetStoredProcCommand("TheStoredProc");
int numberOfAffectedRows = db.ExecuteNonQuery(cmd);
...


Сама процедура TheStoredProc в базе выглядит примерно так:

PROCEDURE TheStoredProc 
as

    declare @Var1 int
    
    SET NOCOUNT ON;
...............
insert into [Workflows]
    (
        WorkflowInstanceID,
        Status
    )
    select WorkflowInstanceID, 1
        from #tmp
        

    DROP TABLE #tmp


Всё это писал не я; но из контекста следует что Клиент ожидает что в результате вызова ExecuteNonQuery ему вернётся в numberOfAffectedRows количество строк вставленных процедурой вот в этом операторе INSERT – “insert into [Workflows] …”.

Причём – только им. В процедуре чуть выше есть ещё один insert; но по контексту очевидно что Клиенту нужно именно и только количество строк вставленных оператором “insert into [Workflows]…”

Баг состоит в том что в результате выполнения этой процедуры кодом Клиента в его переменной numberOfAffectedRows оказалось число 464; а судя по содержимому базы, должно было быть только 419. Всё усложняется тем что баг “трудноповторимый” – его заметили раз на Production SQL Server-е; а вот повторить его на своём тестовом мне пока не удалось – возвращается правильное количество строк в numberOfAffectedRows.

Моя версия такова: виновником бага я считаю оператор “SET NOCOUNT ON” в начале процедуры TheStoredProc. Вот здесь [url=https://social.msdn.microsoft.com/Forums/en-US/e85ad5e5-a30e-4ccf-aeab-0774185e7576/set-nocount-on-and-sqlcommandexecutenonquery-and-sqldataadapterupdate?forum=adodotnetdataproviders] говорится:



I have heard few side effects of using "SET NOCOUNT ON"
a. SQLCommand.ExecuteNonQuery function returning wrong number of rows if the stored procedure has SET NOCOUNT ON.




“wrong number of rows” – как раз то что у меня. Правда, на форумах в других подобных случаях я чаще всего встречал такие сообщения: “в случае использования SET NOCOUNT ON в процедуре метод ExecuteNonQuery возвращает -1”. У меня же, как видите, не -1 а “несколько большее число, чем правильное”.

Других версий у меня пока нет.
Что вы об этом думаете? Правдоподобна моя версия? Так как баг я пока ни разу не воспроизвёл в тестовой среде, мне лишь остаётся оценивать правдоподобность версий…
Исправить баг я предполагаю вставив в процедуре “SET NOCOUNT OFF” прямо перед “insert into [Workflows]…”. На тестовом сервере попробовал – всё выходит правильно. Но и (как я сказал) старый вариант на тестовом сервере тоже работает правильно…
Отредактировано 16.04.2015 15:18 KellyLynch . Предыдущая версия . Еще …
Отредактировано 16.04.2015 15:14 KellyLynch . Предыдущая версия .
set nocount on
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.