powered by simpleCommunicator - 2.0.33     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Использует ли метод DbCommand.Cancel тайм-аут?
4 сообщений из 4, страница 1 из 1
Использует ли метод DbCommand.Cancel тайм-аут?
    #39973622
KellyLynch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня такая проблема: моё .NET приложение вызвало на MS SQL Server хранимую процедуру используя DBCommand.ExecuteScalar(). Процедура выполняется долго. В это время другой thread этого же приложения захотел отменить (cancel) этот вызов; и вызвал метод DbCommand.Cancel(). Я ожидал что тут же тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread) сгенерирует exception. Но – ничего не произошло.
Почему? Может быть – потому что тот объект DbCommand имеет большой (много часов) тайм-аут в свойстве CommandTimeout ? Может быть, метод DbCommand.Cancel() имеет логику вроде такой: “сперва подождём время DbCommand.CommandTimeout, и только потом делаем abort выполняющейся SQL-команде ” - ? Такая логика выглядит странно; но другого объяснения пока не имею.

Документация про метод Cancel ( https://docs.microsoft.com/en-us/dotnet/api/system.data.common.dbcommand.cancel?view=netframework-4.7.2) ничего про это не говорит.
...
Рейтинг: 0 / 0
Использует ли метод DbCommand.Cancel тайм-аут?
    #39973640
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чем вас не устраивает ExecuteScalarAsync(CancellationToken)?
...
Рейтинг: 0 / 0
Использует ли метод DbCommand.Cancel тайм-аут?
    #39973643
KellyLynch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.Pro
Чем вас не устраивает ExecuteScalarAsync(CancellationToken)?


Если честно – я раньше про этот CancellationToken и не слышал :-) У меня есть старый код написанный много лет назад неизвестно кем; и он использует вот именно ту схему что я привёл выше – без CancellationToken. Переписать этот код на CancellationToken можно; спасибо за этот совет.
Но всё-таки – может быть знаете, почему в вышеописанной схеме не сработал Cancel() вызванный из другого потока?
...
Рейтинг: 0 / 0
Использует ли метод DbCommand.Cancel тайм-аут?
    #39973756
KellyLynch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KellyLynch
Но всё-таки – может быть знаете, почему в вышеописанной схеме не сработал Cancel() вызванный из другого потока?


Обновление по проблеме: я воссоздал ситуацию в установленном на моём PC сервере SQL Server 2012 и увидел вот что:

1. Вызванный из другого потока DbCommand.Cancel() вполне себе работает правильно.
Делает то чего ожидалось: тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread) сгенерирует exception. Моя версия про “Может быть – потому что тот объект DbCommand имеет большой (много часов) тайм-аут в свойстве CommandTimeout ? Может быть, метод DbCommand.Cancel() имеет логику вроде такой: “сперва подождём время DbCommand.CommandTimeout, и только потом делаем abort выполняющейся SQL-команде ” - ?” не подтвердилась – и слава богу.

2. Другое дело, что это всё может (в определённых обстоятельствах) занять много времени. То есть DbCommand.Cancel() возвращается-то быстро; но это всего лишь значит что “процесс абортирования текущей команды начался”. Как быстро этот “процесс абортирования” завершится – зависит от того, сколько времени SQL Server-у понадобится на то чтобы прервать (и сделать rollback) текущую транзакцию.
А в конкретно моём случае вызываемая SQL процедура как раз и имела транзакцию внутри себя. Там был использовался SQL курсор которых ходил по большому списку IDs; и для каждого извлечённого значения из этого списка он делал так:

Код: c#
1.
2.
3.
4.
5.
BEGIN TRAN MyTran

EXEC MySubProc()

COMMIT TRAN ProcessAProduct  




Ну вот – ежели этот самый “EXEC MySubProc()" к моменту вызова метода Cancel() успел много чего поменять в базе, то с момента вызова метода Cancel() “всё сделанное” надо откатить обратно (Rollback). Если “успел много чего поменять в базе” составляет десятки миллионов строк, то и отмена займёт много секунд (а то и – минут). Всё это время в моём .NET приложении “тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread)” ничего не генерирует и не возвращает управление, а терпеливо ждёт пока SQL сервер закончит abort моей процедуры.

Итак, всё объяснимо пока, кроме одного: когда я всё это передал автору упомянутой процедуры MySubProc (я про неё пока ничего не знаю) он сказал что “вряд ли моя процедура может что-то выполнять целый час и изменять десятки миллионов строк; обычно она успевает за минуту)”.
Придётся мне тогда копать MySubProc.

Возможно – кто то прочитав этот мой пост, сможет мне дать какие нибудь ещё полезные подсказки? Я вот про что: а вдруг на проблему "а почему же так долго SQL Server не может сделать abort для EXEC MySubProc(), ведь эта процедура вроде бы работает довольно быстро?" как-то влияет тот факт что (см выше) EXEC MySubProc() вызывается много раз - см мои слова " ...SQL курсор которых ходил по большому списку IDs; и для каждого извлечённого значения из этого списка он делал так:.. ". Мне кажется что тот факт что этих вызово много - несущественен; ведь транзакия открывается перед каждый из вызовов и закрывается полсле каждого из них. Или тут есть какой-то "подвох" которго я пока не вижу?
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Использует ли метод DbCommand.Cancel тайм-аут?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]