Как весь код внутри блока TransactionScope на самом деле не выполняется до тех пор, пока область не будет зафиксирована или отменена?

Я читал о TransactionScope и эту статью, но я все еще не понимаю двух вещей:

  1. Когда SqlCommand.ExecuteNonQuery выполняется, он на самом деле не выполняется до тех пор, пока не будет вызван scope.Complete()? Если это правда, то где все операции, которые были выполнены в рамках области, остаются и ждут scope.Complete() или scope.Rollback()?
  2. Когда создается экземпляр TransactionScope, как он предотвращает выполнение SqlCommand.ExecuteNonQuery и ожидание scope.Complete() или scope.Rollback()? Создает ли он какое-то "место" и SqlCommand как-то знает об этом и помещает туда инструкции?

person theateist    schedule 19.07.2012    source источник
comment
Базы данных довольно сложны - все транзакции в ваших вызовах C # будут в контексте БД, как говорит BonyT - хотя вам не нужно знать, как это делает база данных, это, безусловно, интересный материал (и может дать вам некоторые идеи)! Некоторые другие вопросы SO охватывают этот stackoverflow.com/ questions / 3466632 /   -  person Charleh    schedule 19.07.2012


Ответы (4)


[1] Когда выполняется SqlCommand.ExecuteNonQuery, он на самом деле не выполняется до тех пор, пока не будет вызвана scope.Complete ()?

Нет, это не так. Ваша команда выполняется в строке, в которой вы вызываете ExecuteNonQuery. Однако интересно знать, где хранятся все изменения. Изменения не идут напрямую в затронутые таблицы на стороне сервера, скорее, изменения хранятся во временном месте (опять же на стороне сервера), что приводит к ответу на ваш второй вопрос.

[2] Когда создается экземпляр TransactionScope, как он предотвращает выполнение SqlCommand.ExecuteNonQuery и ожидает выполнения scope.Complete () или scope.Rollback ()?

Это не предотвращает как таковое действие , но поскольку результат действия сохраняется во временном месте, вы должны либо объединить эти изменения с основной таблицей ( s) - scope.Commit() или отменить эти изменения - scope.Rollback() (или что-то еще, что используется для отмены изменений в конкретном поставщике данных базы данных)

person oleksii    schedule 19.07.2012

TransactionScope скрывает множество вещей под покровом.

Когда вы создаете TransactionScope, все, что вы делаете внутри него, находится в контексте транзакции (транзакций) базы данных. Таким образом, операторы SQL будут выполняться немедленно, но их эффекты будут внутри транзакции, так что другие процессы не будут знать о их возникновении до тех пор, пока транзакция не будет зафиксирована.

Если вы работаете только с одной базой данных, то транзакция открывается для нее и фиксируется или откатывается в зависимости от того, используете ли вы .Complete () или нет. Также, если в контексте TransactionScope возникает исключение, транзакция откатывается.

Если вы работаете с несколькими базами данных, транзакция создается в каждой из них, и координатор распределенных транзакций Microsoft (MSDTC) управляет всей транзакцией. Когда вы .Complete () MSDTC будет инструктировать каждую отдельную транзакцию о фиксации.

Примечание MSDTC не ограничивается базами данных - дополнительную информацию см. здесь.

person BonyT    schedule 19.07.2012
comment
Нет TransactionScope.Rollback. Я не очень знаком с этим, но я почти уверен, что using-statement (или dispose) приведет к откату транзакции, если она не была завершена раньше. Следовательно, TransactionScope.Complete зафиксирует транзакцию, тогда как отсутствующий Complete откатит транзакцию при удалении. - person Tim Schmelter; 19.07.2012

Область транзакции не препятствует выполнению кода, она предотвращает фиксацию транзакции. Таким образом, в случае SqlCommand.ExecuteNonQuery, поскольку он находится внутри транзакции, SqlCommand смотрит на координатор транзакции и видит, что это было вызвано внутри транзакции, поэтому, когда он подключается к SQL Server, транзакция сохраняется, поэтому SQL Записывает данные в базу данных, но они недоступны для чтения, если транзакция не зафиксирована (или кто-то выполняет «грязное чтение»). Если Complete никогда не вызывается, то когда TransactionScope удаляется, он откатывается, и SQL может отменить вставку (или что-то еще, что он сделал).

Все, что использует транзакции (например, другие технологии баз данных), должно реализовывать свой .Net-код для поддержки транзакций.

Транзакции в основном используются в базах данных, но теоретически для их поддержки может быть создан другой код.

Но, чтобы ответить на ваш вопрос, код не останавливается до тех пор, пока не будет вызван метод Complete(), он не будет запущен, но в транзакции.

person DaveShaw    schedule 19.07.2012

Это может помочь в ваших вопросах: вы можете включить трассировку для MSDTC, чтобы увидеть транзакцию.

См. Ссылку для получения подробной информации http://support.microsoft.com/kb/899115

Надеюсь это поможет..

person HatSoft    schedule 19.07.2012
comment
Я открыл Local DTC в Component Service оснастке в MMC, но я действительно не вижу транзакций. Другой вопрос: можно ли увидеть транзакцию MSMQ в Local DTC? - person theateist; 26.07.2012