2015-03-05 3 views
7

Я читал документ из шаблонов Microsoft & практики группы (Data Access for Highly-Scalable Solutions: Using SQL, NoSQL, and Polyglot Persistence).Использует TransactionScope в Entity Framework запрашивает хорошую идею?

В главе 3 в разделе "Retrieving Data from the SQL Server Database" авторы обсуждают использование Entity Framework для загрузки объектов из базы данных. Вот немного их пример кода:

using (var context = new PersonContext()) 
{ 
    Person person = null; 

    using (var transactionScope = this.GetTransactionScope()) 
    { 
     person = context.Persons 
      .Include(p => p.Addresses) 
      .Include(p => p.CreditCards) 
      .Include(p => p.EmailAddresses) 
      .Include(p => p.Password) 
      .SingleOrDefault(p => p.BusinessEntityId == personId); 

     transactionScope.Complete(); 
    } 

    // etc... 
} 

Примечание использование объема пользовательских транзакций с помощью метода GetTransactionScope, реализованная в их базовом классе контекста, как так:

public abstract class BaseRepository 
{ 
    private static TransactionOptions transactionOptions = new TransactionOptions() 
    { 
     IsolationLevel = IsolationLevel.ReadCommitted 
    }; 

    protected virtual TransactionScope GetTransactionScope() 
    { 
     return new TransactionScope(TransactionScopeOption.Required, transactionOptions); 
    } 
} 

Working with Transactions (EF6 Onwards) на MSDN гласит:

Во всех версиях Entity Framework всякий раз, когда вы выполняете SaveChanges() для вставки, обновления или удаления в базе данных, фреймворк будет обертывать эту операцию в транзакции [... ] уровень изоляции транзакции - это любой уровень изоляции, который поставщик базы данных считает своей настройкой по умолчанию. По умолчанию, например, на SQL Server это READ COMMITTED. Entity Framework не переносит запросы в транзакции. Эта функция по умолчанию подходит для большого количества пользователей

Смелый акцент делается на моем.

Мой вопрос: является использование TransactionScope, как показано выше, overkill, особенно для чтения данных, при использовании Entity Framework?

(я понял, после размещения, что ответ на этот вопрос может быть несколько на основе мнений, сожалею об этом.)

+0

С этим 'isolLevel' этот код переполняется, если транзакция содержит только операцию чтения. Но если 'isolLevel' является' ReadUncommited', этот код позволит вам прочитать грязную строку (еще не объявленную). –

+1

Вам следует избегать области транзакции, если она не служит коммерческой цели. это позволит избежать взаимоблокировок и проблем с производительностью. – MichaelD

ответ

5

Вопрос немного открыт. Но может оказаться полезным для людей, которые узнают о грязных чтениях. Изоляция и EF. И вы прочитали EF Transaction Scope ef6, и у нас есть четкий вопрос.

Как правило, я бы сказал, пусть EF управляет областью. Начинающие не рассматривают незафиксированные чтения и являются хорошим дефолтом для EF.

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

Итак, настоящий вопрос.
Полезно ли включать такие защитные программы в изоляции.

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

Oracle и SQL-сервер по умолчанию Read Committed. Я бы ожидал этого и в других БД. Поэтому я заключу, скорее всего, ненужную защиту, которая добавит сложности.
Я бы не добавил его в свой код.

+0

EF не говорит, что он имеет транзакцию по умолчанию за пределами SaveChanges, создает ли TransactionScope при создании контекста? –

2

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

1

Для обеспечения целостности данных иногда полезно использовать явно определенную транзакцию с несколькими операторами, так что если какая-либо часть транзакции завершится с ошибкой, все ее откатит. Решение о том, следует ли использовать транзакцию, не следует вводить в легкое. Явные транзакции, особенно распределенные, приносят существенную выгоду для производительности и открывают систему до взаимоблокировок и возможность того, что транзакция может быть оставлена ​​открытой, заблокировать затронутую таблицу и заблокировать все другие транзакции. Кроме того, код гораздо сложнее разрабатывать и поддерживать.

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

1

Вы прочитали следующую ссылку? https://msdn.microsoft.com/en-us/library/vstudio/bb738523%28v=vs.100%29.aspx

Если бы вы использовали обычное поведение saveChanges без его начала части транзакции, вы не смогли бы продлить транзакцию за пределами базы данных. Использование области транзакции, как в приведенной выше ссылке, делает очередь сообщений частью транзакции. Поэтому, если по какой-либо причине отправка сообщения завершается с ошибкой, транзакция также терпит неудачу.

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

Смежные вопросы