Задать вопрос
@saneok44

C# SqlTransaction блочит таблицу, как обойти блокировку или что делаю не так?

Есть "мелкие" методы которые подключаются к базе получают значение и закрывают подключение.

Есть две SQLCommand последовательные.

1. Создаю подключение.
2. Бидню транзакцию к подключению.
2.1. Биндю команду к подключению и транзакции.
3. Исполняю первую команду command_1.ExecuteNonQuery();
4. Хочу получить значение из тб. вызывая "мелкие" метод. И он вываливается по таймауту.
5. До исполнения второй команды разумеется дело не дошло.

Окей меняю мелкий метод передавая ему транзакцию и коннект, чтобы он стал частью транзакции.
Снова выполняю пункты 1., 2., 2.1, 3.
4. Теперь мелкий метод став частью транзакции получает значение из тб.
5. Выполняю command_2.ExecuteNonQuery();
6. transaction.Commit();

После исполнения первой транзакции и до выполнения второй заметил что блочится вся таблица и все коннекты и запросы вываливаются по таймауту. Я даже на момент транзакции запустил sql management studio и не смог выполнить запрос, пока транзакция на C# не закончилась. Ну я тут подумал хм ... транзакция блочит тб да как то странно ...

Открыл sql management studio вставил первую команду и до commit сделал задержку в 1 минуту.
begin transaction
...
WAITFOR DELAY '00:01';
commit transaction
Затем выполнил параллельно другую команду и она спокойно выполнилась до того как закоммитилась первая команда.

Вот и я не понимаю, почему с# транзакция блочит таблицу. Когда те же самые операции делаю через sql management studio без всяких блокировок.

Игрался с уровнями блокировок connection.BeginTransaction(IsolationLevel.....) ни к чему это не привело. Как блочилась вся тб так и блочится и ни одна учетка не может выполнить запрос без завершения транзакции.

Краткий листинг:
SqlConnection connection = new SqlConnection(ark.stringConnect);
connection.Open();
SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.......);
SqlCommand command1 = _Delete(userID, periodID);
command1.CommandTimeout = 60;
command1.Connection = connection;
command1.Transaction = transaction;
command1.ExecuteNonQuery();

string S = "мелкий_метод(получить какое то значение)" он делает новое подключение и получает значение

SqlCommand command2 = Command_UpdateCascadePeriod(userID, uPeriod);
command2.CommandTimeout = 60;
 command2.Connection = connection;
command2.Transaction = transaction;
command2.ExecuteNonQuery();

transaction.Commit();
  • Вопрос задан
  • 146 просмотров
Подписаться 1 Средний 5 комментариев
Ответ пользователя MVV К ответам на вопрос (2)
@mvv-rus
Настоящий админ AD и ненастоящий программист
Игрался с уровнями блокировок connection.BeginTransaction(IsolationLevel.....) ни к чему это не привело.

Попробуйте обе транзации - и основную, и в мелком методе - делать с уровнем изоляции Snapshot.
По умолчанию изоляция транзакций в MS SQL реализуется через блокировки (изначально - обрабатываемых записей, но может переползти и на всю таблицу).
А вообще, при работе с незакрытй транзакциейоя бы передавал в мелкий метод то подключение, на котором открыта транзакция, чтобы он работал с ней. Можно сделать этот параметр необязательным (null по умолчанию) и в случае, если он не передан - открывать дополнительное подключение.
Ответ написан