Как глобально изменить IsolationLevel всех транзакций Entity Framework - PullRequest
7 голосов
/ 26 февраля 2011

Я оцениваю EF для моих следующих новых приложений.

Как я могу глобально изменить IsolationLevel всех транзакций EF в приложении? Пример: Предположим, я хочу использовать «Read Committed Snapshot».

Несмотря на то, что можно указывать IsolationLevel, когда я все равно явно нуждаюсь в TransactionScope (см. Код ниже), было бы ужасно инкапсулировать каждую операцию сохранения EF в TransactionScope.

 'OK
    Using tsc As New TransactionScope(TransactionScopeOption.RequiresNew, TransactionOption.ReadCommitted)
        UpdateShoppingCart
        EnqueueNewOrder
        SendConfirmationEmail
        tsc.Complete
    End Using

    'Is this really the only way to avoid Serializable?
    Using tsc As New TransactionScope(TransactionScopeOption.RequiresNew, TransactionOption.ReadCommitted)
      _ctx.SaveChanges()
      tsc.Complete
    End Using

    Class TransactionOption
        Public Shared ReadOnly ReadCommitted As New TransactionOptions() With {
            .IsolationLevel = IsolationLevel.ReadCommitted,
            .Timeout = TransactionManager.DefaultTimeout
            }
    End Class

Полагаю, смешивание IsolationLevles не очень хорошая идея. Я не прав с этим?

При использовании Serializable и SQL Server (в отличие от Oracle) вставка простого невинно выглядящего чтения может привести к блокировке блокировки преобразования.

Из EF FAQ: "Рекомендуется использовать транзакции READ COMMITTED и использовать READ COMMITTED SNAPSHOT ISOLATION, если вам нужно, чтобы читатели не блокировали писателей, а писатели не блокировали читателей."

Я не понимаю, почему EF по умолчанию использует Serializable и так сложно изменить уровень изоляции по умолчанию - с SQL Server (в отличие от Oracle с несколькими версиями) по умолчанию используется пессимистическая модель параллелизма. Вариант конфигурации должен быть очень простым для реализации - или я что-то здесь упускаю?

Ответы [ 2 ]

9 голосов
/ 26 февраля 2011

Я почти уверен, что уровень изоляции транзакции EF по умолчанию зависит от используемого поставщика базы данных.SaveChanges выполняет этот код:

    ... 
    try
    {
        this.EnsureConnection();
        flag = true;
        Transaction current = Transaction.Current;
        bool flag2 = false;
        if (connection.CurrentTransaction == null)
        {
            flag2 = null == this._lastTransaction;
        }
        using (DbTransaction transaction = null)
        {
            if (flag2)
            {
                transaction = connection.BeginTransaction();
            }
            objectStateEntriesCount = this._adapter.Update(this.ObjectStateManager);
            if (transaction != null)
            {
                transaction.Commit();
            }
        }
    }
    ...

Как видите, BeginTransaction вызывается без указания IsolationLevel.Под капотом создается специфическая для провайдера транзакция с IsolationLevel.Unspecified.Неуказанный уровень изоляции должен приводить к уровню изоляции по умолчанию для сервера / драйвера базы данных.В SQL Server уровень изоляции по умолчанию равен READ COMMITED, поэтому я ожидаю, что он должен использовать его, но я еще не проверял его.

Если вы хотите глобально изменить уровень изоляции, вы можете переопределить SaveChanges в производном от классаиз ObjectContext и обернуть base.SaveChanges() в пользовательский TransactionScope.

0 голосов
/ 26 февраля 2011

В VB может быть ограничение, но в C # вы бы сделали это так:

 TransactionOptions transactionOptions = GetTransactionOptions();
 new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions) 

Обратите внимание, что вторым параметром являетсяactionOptions, его можно создать следующим образом:

 public TransactionOptions GetTransactionOptions()
    {
        TransactionOptions transactionOptions = new TransactionOptions();
        transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
        return transactionOptions;
    }

Поместив приведенный выше код в метод Factory и вызывая этот метод factory всякий раз, когда вам нужны параметры транзакции, вы можете в одном месте изменить все области транзакций в своем решении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...