2009-04-27 2 views
24

См. Приведенный ниже код. Если я инициализирую более одного контекста сущности, тогда я получаю следующее исключение на 2-й набор кода только. Если я прокомментирую второй набор, он работает.Почему TransactionScope не работает с Entity Framework?

{ "Основной поставщик потерпел неудачу на Open."}

Внутренний: { "Связь с основным менеджером транзакций не удалась."}

Внутренний: { "Ошибка HRESULT E_FAIL был возвращен от вызова к COM-компоненту. "}

Обратите внимание, что это пример приложения, и я знаю, что не имеет смысла создавать 2 контекста в строке. Однако у производственного кода есть причина для создания нескольких контекстов в том же TransactionScope, и это не может быть изменено.

Редактировать

Вот предыдущий вопрос я пытаюсь настроить MS-DTC. Он кажется включенным как на сервере, так и на клиенте. Я не уверен, правильно ли он настроен. Также обратите внимание, что одна из причин, которые я пытаюсь сделать, заключается в том, что существующий код в TransactionScope использует ADO.NET и Linq 2 Sql ... Я бы хотел, чтобы они использовали ту же транзакцию. (Это, вероятно, звучит сумасшедшим, но мне нужно, чтобы он работал, если это возможно).

How do I use TransactionScope in C#?

Решение

Брандмауэр Windows блокировал соединения с MS-DTC.

using(TransactionScope ts = new System.Transactions.TransactionScope()) 
     { 
       using (DatabaseEntityModel o = new DatabaseEntityModel()) 
       { 
        var v = (from s in o.Advertiser select s).First(); 
        v.AcceptableLength = 1; 
        o.SaveChanges(); 
       } 

       //-> By commenting out this section, it works 
       using (DatabaseEntityModel o = new DatabaseEntityModel()) 
       { 
        //Exception on this next line 
        var v = (from s1 in o.Advertiser select s1).First();       v.AcceptableLength = 1; 
        o.SaveChanges(); 
       } 
       //-> 

       ts.Complete(); 
     } 

ответ

18

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

Посмотрите на this link для получения дополнительной информации о том, что происходит.

В принципе, если вы убедитесь, что ваш MS-DTC работает и работает правильно, у вас не должно быть проблем с использованием двух соединений ADO.NET - будь то соединения с инфраструктурой сущности или любые другие типы.

+4

Это работает сейчас. Брандмауэр Windows блокировал подключения к MS-DTC. – NotDan

19

Вы можете избежать использования распределенной транзакции пути управления собственной EntityConnection и передавая эту EntityConnection вашего ObjectContext. В противном случае проверьте их.

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=580828&SiteID=1&mode=1 http://forums.microsoft.com/msdn/showpost.aspx?postid=113669&siteid=1&sb=0&d=1&at=7&ft=11&tf=0&pageid=1

EntityConnection conn = new EntityConnection(ConnectionString); 

using (TransactionScope ts = new TransactionScope()) 
{ 
    using (DatabaseEntityModel o = new DatabaseEntityModel(conn)) 
    { 
      var v = (from s in o.Advertiser select s).First(); 
      v.AcceptableLength = 1; 
    } 

    //-> By commenting out this section, it works 
    using (DatabaseEntityModel o = new DatabaseEntityModel(conn)) 
    { 
     //Exception on this next line 
     var v = (from s1 in o.Advertiser select s1).First(); 
       v.AcceptableLength = 1; 
    } 
    //-> 

    ts.Complete(); 
} 
+0

Я не просто использую Entity Framework, поэтому повторное использование EntityConnection также не является простым решением (см. Выше) – NotDan

+6

+1 для избежания кода DTC. Не то чтобы это плохо, просто распределенные транзакции не так легко выбирать. Это тесная связь приложений и ресурсов, которая рискует низкой доступности по дизайну. –

+0

Вы также можете вызвать контекст.Connection.Open(), чтобы вручную управлять им. Вам не нужно создавать EntityConnection вручную –

1

Проблема заключается в том, что 2 разные DataContext создают два различных соединений.

В этом случае транзакция должна быть повышена до распределенной транзакции. Я предполагаю, что ваша проблема связана с согласованием MS DTC (Microsoft Distributed Transaction Coordinator) на сервере и/или с клиентом. Если сервер не настроен на разрешение удаленных подключений для MSDTC, например, вы столкнетесь с таким исключением.

Вы можете обратиться к this MS page, например, для устранения неполадок MSDTC, а Google заполнен до краев вопросами об изделиях/форумах.

Теперь это может быть что-то другое, но это действительно звучит, как проблема MSDTC.

+0

См. Мое редактирование выше. Я думаю, что вы правы, и я пытаюсь настроить MS-DTC ... Я не уверен, почему он не работает. – NotDan

0

Я написал ответ в другом вопросе о том, как диагностировать транзакции MSDTC.

Возможно, этот ответ вам поможет.

How do I enable MSDTC on SQL Server?

3

BTW вы должны рассмотреть возможность использования SaveChanges (ложных) в сочетании с AcceptChanges() при использовании явных транзакций, как это.

Таким образом, если что-то не в SaveChanges (ложных), то ObjectContext не отбрасывают изменения, так что вы можете повторно применить позже или сделать некоторые ошибки регистрации и т.д.

Посмотреть этот пост для получения дополнительной информации: http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

Приветствия

Alex

5

Добавить C: \ Windows \ msdtc.exe исключений брандмауэра на обоих брандмауэра и сервера. Я потратил веки обезьянами вокруг открытия определенных номеров портов и диапазонов безрезультатно, прежде чем я это сделал.

0

У меня были подобные ошибки при использовании DTC при чтении сообщений из очереди MQ, их обработке и хранении в базе данных SQL Server 2005 Express Edition. У меня недостаточно времени для расследования до конца, вызвала ли это проблема 2005 года или экстенсивно Express Edition, но переход на 2008 год Standard исчез из-за этого конкретного поведения.

4

Я собираюсь придерживаться этого здесь, потому что я провел 3 часа с коллегой вчера, отлаживая эту проблему. Каждый ответ, связанный с этим, говорит, что это всегда проблема брандмауэра; однако в нашем случае это было не так. Надеюсь, это избавит кого-то от боли.

Ситуация, в которой мы находимся, заключается в том, что мы в настоящее время находимся в процессе перехода на Entity Framework. Это означает, что у нас есть части кода, в которых внутри одного соединения транзакции открываются как напрямую, так и с использованием new SqlConnection(connectionString).Open() и косвенно с использованием контекста данных EF.

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

Причина ошибки в конечном итоге оказалась в том, что если вы не укажете аргумент Application Name= вашей строке соединения, то Entity Framework добавит по умолчанию (что-то вроде EntityFrameworkMUF).Это означает, что у вас есть два различных соединение в вашем пуле соединений:

  1. тот, который вы открываете вручную, без Application Name= аргумента
  2. автоматически генерируемых один суффикс Application Name=EntityFrameworkMUF

и это не представляется возможным откройте два отдельных соединения внутри одной транзакции. В производственном коде указано имя приложения; следовательно, это сработало; в тестовом коде нет. Указание аргумента Application Name= исправило ошибку для нас.

+0

Моя проблема была еще более конкретной, одна строка подключения использовала 'App = EntityFramework', другая использовала' Application Name = EntityFramework'. Лучше всего протестировать, если это ваша проблема, заключается в том, чтобы скопировать строку подключения из одного контекста и передать ее в качестве параметра при создании второго. –

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