Изменять уровень изоляции только в отдельных транзакциях ADO.NET

Каков наилучший способ реализации различных уровней изоляции для отдельных транзакций при использовании клиентской среды, ORM или аналогичных для построения запросов, которые не поддерживают подсказки запросов, такие как WITH (NOLOCK)?

Представьте себе приложение, использующее уровень ReadUncommitted для ряда сложных и длительных запросов (хорошо осведомленных о связанных рисках), и оно должно работать с NHibernate и его критериями запроса (или QueryOver / LINQ, просто без объединения строк!).

NHibernate не поддерживает подсказку with (nolock) (кроме случаев использования собственного SQL, который в настоящее время используется во многих случаях).

Итак, чтобы заменить собственные строки SQL и их утомительный строительный код, я хочу использовать транзакции с IsolationLevel.ReadUncommitted для замены 'with (nolock)'.

Но соединение остается на измененном уровне изоляции даже после фиксации / отката, когда все работает на новом уровне. Даже после connection.Close () он возвращается в пул соединений и повторно используется с измененным уровнем изоляции.

Первоначально я заметил это, потому что я тестировал открытие соединения с уровнем изоляции Snapshot и отправку простого запроса, чтобы отключить Read Uncommitted, если включен режим Snapshot в базе данных (простой переход к снимку в общем случае невозможен). В тестовой базе данных отключен режим моментальных снимков, поэтому я получил исключение и установил для моей переменной UseReadUncommitted значение true в блоке catch, но более поздние запросы из «нового» / повторно используемого соединения все равно получили то же исключение.

Я написал простой класс, чтобы обернуть обработку транзакций в блок использования, автоматически сбрасывая IsolationLevel в .Dispose (). Но это, кажется, вызывает два дополнительных обращения к БД, и я не уверен, может ли измененный уровень изоляции «пережить» удаление в определенных ситуациях и повлиять на другие запросы. Код работал с первой попытки, он предназначен для простых соединений / транзакций ADO.NET (я сделаю еще один для сессий NHibernate, если хорошо!).

Какие-либо предложения?

public class TransactionContainerTempIsolationLevel : IDisposable
{
    public IsolationLevel OldIsolationLevel { get; private set; }

    public IsolationLevel TempIsolationLevel { get; private set; }

    public IDbTransaction Transaction { get; private set; }

    private readonly IDbConnection _conn;

    public TransactionContainerTempIsolationLevel(IDbConnection connection, IsolationLevel tempIsolationLevel)
    {
        _conn = connection;
        LocalIsolationLevel = localIsolationLevel;

        var checkTran = _conn.BeginTransaction();
        if (checkTran.IsolationLevel == tempIsolationLevel)
        {
            Transaction = checkTran;
        }
        else
        {
            OldIsolationLevel = checkTran.IsolationLevel;
            checkTran.Dispose();
            Transaction = _conn.BeginTransaction(tempIsolationLevel);
        }
    }

    public void Dispose()
    {
        Transaction.Dispose();
        if (OldIsolationLevel != TempIsolationLevel)
        {
            using (var restoreTran = _conn.BeginTransaction(OldIsolationLevel))
            {
                restoreTran.Commit();
            }
        }
    }
}

Ответы на вопрос(1)

Ваш ответ на вопрос