Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
KellyLynch Member Откуда: Сообщений: 94 |
У меня есть: MS SQL Server 2008 R2; C# приложение – его клиент Я встретил следующий (причём невоспроизводимый регулярно) баг. Такой вот код на клиенте приносит “количество затронутых строк” большее чем их должно быть на самом деле: … DbCommand cmd = db.GetStoredProcCommand("[b]TheStoredProc[/b]"); int numberOfAffectedRows = db.ExecuteNonQuery(cmd); …Сама процедура TheStoredProc в базе выглядит примерно так: PROCEDURE TheStoredProc as declare @Var1 int [color=blue]SET NOCOUNT ON;[/color] .................... [b]insert into [Workflows][/b] ( WorkflowInstanceID, Status ) select WorkflowInstanceID, 1 from #tmp DROP TABLE #tmp Процедуру писал не я; но из контекста следует что Клиент ожидает что в результате вызова ExecuteNonQuery ему вернётся в numberOfAffectedRows количество строк вставленных процедурой вот в этом операторе INSERT – “insert into [Workflows] …”. Причём – только этим insert-ом. В процедуре чуть выше есть ещё один 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[/url] говорится:
“wrong number of rows” – как раз то что у меня. Правда, на форумах в других подобных случаях я чаще всего встречал такие сообщения: “в случае использования SET NOCOUNT ON в процедуре метод ExecuteNonQuery возвращает -1”. У меня же, как видите, не -1 а “несколько большее число, чем правильное”. Других версий у меня пока нет. Что вы об этом думаете? Правдоподобна моя версия? Так как баг я пока ни разу не воспроизвёл в тестовой среде, мне лишь остаётся оценивать правдоподобность версий… Исправить баг я предполагаю вставив в процедуре “SET NOCOUNT OFF” прямо перед “insert into [Workflows]…”. На тестовом сервере попробовал – всё выходит правильно. Но и (как я сказал) старый вариант на тестовом сервере тоже работает правильно… |
||
16 апр 15, 18:06 [17525820] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104751 |
Ага. ОБС - одна бабка сказала. Ниже цитируют офф.хелп SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. Что такое DONE_IN_PROC вы можете узнать здесь https://msdn.microsoft.com/en-us/library/dd340553.aspx |
||
17 апр 15, 08:19 [17527236] Ответить | Цитировать Сообщить модератору |
KellyLynch Member Откуда: Сообщений: 94 |
Исходя из этого Вы считаете невозможным описанный выше сценарий? Когда включение SET NOCOUNT ON привело к тому что ExecuteNonQuery() стал возвращать больше строк чем должен? Если почитать официальное описание DONE_IN_PROC, то получается: установка в процедуре SET NOCOUNT ON может привести к тому что ExecuteNonQuery() возвратит меньше строк чем должен. В моём же случае он возвратил больше строк чем должен... Согласны с моими рассуждениями? Или я что-то упустил? |
||||
17 апр 15, 10:32 [17527888] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104751 |
Должно кому ? Где еще, кроме вашего неизвестного клиентского кода, проверялось что должно возвращаться и что возвращается ?
А где написано, что скрывется за вашим многоточием между SET NOCOUNT ON и insert into [Workflows] ? |
||||
17 апр 15, 10:37 [17527929] Ответить | Цитировать Сообщить модератору |
felix_ff Member Откуда: Moscow Сообщений: 1698 |
PROCEDURE TheStoredProc @rows INT = NULL OUTPUT as declare @Var1 int [color=blue]SET NOCOUNT ON;[/color] .................... [b]insert into [Workflows][/b] ( WorkflowInstanceID, Status ) select WorkflowInstanceID, 1 from #tmp SET @rows = @@ROWCOUNT DROP TABLE #tmp DbCommand cmd = db.GetStoredProcCommand("[b]TheStoredProc[/b]"); db.ExecuteNonQuery(cmd); int numberOfAffectedRows = cmd.Parameters("@rows").Value; ну а если так? |
||||||
17 апр 15, 13:37 [17529153] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9646 |
1. В режиме nocount on ExecuteNonQuery будет возвращать -1. Если это не так, значит часть DML в пакете выполнялись таки с nocount off; 2. Внимательно прочитав статью документации по ExecuteNonQuery, можно понять, что использовать результат этой функции для определения количества обработанных строк можно только в простейших случаях, да и то впоследствии можно получить сюрпризы. |
||
17 апр 15, 13:44 [17529218] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |