Это не плохая практика.Следует помнить одну вещь: все операторы будут использовать неявную транзакцию, которую они будут автоматически фиксировать, когда оператор закончится.То есть SELECT (как в SELECT, используемом Fill) будет всегда использовать транзакцию, вопрос в том, придется ли ей запускать ее самостоятельно или она будет использовать существующую.
Есть ли разница между количеством, типом и продолжительностью блокировок, полученных SELECT в неявной транзакции, и явной транзакцией?В модели транзакции по умолчанию (READ COMMITTED изоляция) NO ее нет.Поведение идентично и неразличимо.При других уровнях изоляции (повторяемое чтение, сериализация) существует различие, но оно является необходимым для достижения желаемого более высокого уровня изоляции, и использование явной транзакции - это только способ достижения этого желаемого уровня изоляции, при необходимости.
Кроме того, если SELECT должен прочитать результаты ожидающей транзакции (еще не зафиксированной), как в вашем примере (считывание сгенерированных идентификаторов), тогда нетДругой способ .SELECT должен быть частью транзакции, сгенерировавшей идентификаторы, в противном случае он не сможет увидеть эти незафиксированные идентификаторы!
Однако следует соблюдать осторожность.Я полагаю, что в вашем распоряжении прекрасный инструмент, который может значительно облегчить обработку всех транзакций: System.Transactions .Весь код ADO.Net учитывает системные транзакции и автоматически регистрирует любое соединение и команду в ожидающей транзакции, если вы просто объявите TransactionScope
.То есть, если функция Foo объявляет TransactionScope
и затем вызывает функцию Bar, если Bar выполняет любое ADO.Net operatio, она автоматически будет частью транзакции, объявленной в Foo, даже если Bar делает ничего явно.TransactionScope
подключается к контексту потока, и все вызовы ADO.Net, вызываемые Bar, автоматически проверяют этот контекст и используют его.Обратите внимание, что я действительно имею в виду любой вызов ADO.Net, включая вызовы провайдера Oracle.Увы, хотя есть предупреждение: с использованием нового TransactionScope () Считается вредным : конструктор по умолчанию TransactionScope
создаст сериализуемую транзакцию, которая является избыточной.Вы должны использовать конструктор, который принимает объект TransactionOptions
и изменить поведение на ReadCommitted.Второй недостаток TransactionScope
заключается в том, что вы должны быть очень осторожны при управлении соединениями: если вы открываете более одного соединения в области действия, они будут зарегистрированы в распределенной транзакции, которая медленная и требует настройки MSDTC,и приводит ко всем видам трудно отлаживаемых ошибок.Но в целом я упал, что преимущества использования TransactionScope
перевешивают проблемы, и полученный код всегда более элегантен, чем явный обход IDbTransaction
.