2013-08-16 2 views
3

Кто-нибудь знает о любых случаях использования области транзакции, которую транзакция перерастает в DTC, когда несколько подключений НЕ открыты.Транзакция перешла на код DTC Нет нескольких соединений

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

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

Однако, у меня есть клиент, где они получают исключение

Произошла ошибка. Csla.DataPortalException: DataPortal.Update не удалось (базовый провайдер отказал при открытии.) ---> Csla.Reflection.CallMethodException: вызов метода EditableCategory.DataPortal_Update не удалось ---> System.Data.EntityException: базовый поставщик отказался при открытии. ---> System.Transactions.TransactionManagerCommunicationException: сетевой доступ для Distributed Transaction Manager (MSDTC) отключен. Включите DTC для доступа к сети в конфигурации безопасности для MSDTC с помощью инструмента администрирования служб компонентов. ---> System.Runtime.InteropServices.COMException: диспетчер транзакций отключил поддержку удаленных/сетевых транзакций.

Опять же, я уверен, что в пределах области действия открыто только одно соединение. Взглянуть.

protected override void DataPortal_Update() 
    { 
     using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, System.Transactions.TransactionManager.MaximumTimeout)) 
     { 
      //get the dal manager he knows which dal implementation to use 
      using (var dalMgr = DataAccess.BusinessObjectsDalFactory.GetManager()) 
      { 
       //get the category dal implementation 
       var ecDal = dalMgr.GetProvider<DataAccess.BusinessObjectDalInterfaces.ICategoryDAL>(); 

       //assume all the data is good at this point so use bypassproperty checks 
       using (BypassPropertyChecks) 
       { 
        var catData = new Models.Category { CategoryId = CategoryId, CategoryName = CategoryName, LastChanged = TimeStamp }; 

        ecDal.UpdateCategory(catData); 

        TimeStamp = catData.LastChanged; 
       } 
      } 

      ts.Complete(); 
     } 

     base.DataPortal_Update(); 
    } 

public class DalManager : Core.Sebring.DataAccess.IBusinessObjectsDalManager {private static string _typeMask = typeof(DalManager).FullName.Replace("DalManager", @"{0}"); 

public T GetProvider<T>() where T : class 
{ 
    var typeName = string.Format(_typeMask, typeof(T).Name.Substring(1)); 
    var type = Type.GetType(typeName); 
    if (type != null) 
    return Activator.CreateInstance(type) as T; 
    else 
    throw new NotImplementedException(typeName); 
} 

public Csla.Data.DbContextManager<DataContext> ConnectionManager { get; private set; } 

public DalManager() 
{ 
    ConnectionManager = Csla.Data.DbContextManager<DataContext>.GetManager(); 
} 

public void Dispose() 
{ 
    ConnectionManager.Dispose(); 
    ConnectionManager = null; 
} 


public void UpdateDataBase() 
{ 
    DatabaseUpgrader.PerformUpgrade(); 
} 
} 

public void UpdateCategory(Models.Category catData) 
    { 
     if (catData == null) return; 
     using (var cntx = DbContextManager<DataContext>.GetManager()) 
     { 
      var cat = cntx.DbContext.Set<Category>().FirstOrDefault(c => c.CategoryId == catData.CategoryId); 

      if (cat == null) return; 

      if (!cat.LastChanged.Matches(catData.LastChanged)) 
       throw new ConcurrencyException(cat.GetType().ToString()); 

      cat.CategoryName = catData.CategoryName; 
      //cntx.DbContext.ChangeTracker.DetectChanges(); 
      cntx.DbContext.Entry<Category>(cat).State = System.Data.EntityState.Modified; 
      cntx.DbContext.SaveChanges(); 
      catData.LastChanged = cat.LastChanged; 
     } 

    } 

Код для DBContextManager доступен, но в общем он просто делает наверняка есть только один DbContext, и, следовательно, одно соединение открыто. Я что-то пропускаю? Я предполагаю, что возможно, что что-то происходит с DBConextManager, поэтому я опубликовал также на форумах CSLA (DBContextManager входит в состав CSLA). Но есть ли кто-нибудь в сценариях, где они уверены, что одно соединение открыто в пределах транзакции, а транзакция перерастает в DTC?

Конечно, я не могу воспроизвести исключение на своей локальной машине dev или любой из наших машин QA.

Любая помощь приветствуется.

Спасибо.

+1

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

+0

Спасибо за предложение. Я об этом не думал. Хотя, я уверен, что открыт только один экземпляр приложения. Я проверю. Поскольку я не могу воспроизвести и должен стрелять в темноте, может потребоваться некоторое время, чтобы проверить, но я буду держать вас в курсе. – andrewramka

ответ

0

Entity Framework может случайным образом попытаться открыть новое соединение при выполнении операций с System.Transactions.TransactionScope

Try добавление наконец заявление и распоряжаться вашей сделки, а также вызвать ваш DbContext и вручную закрыть соединение, это будет меньшим по суммой раз транзакция получает эскалация, но все еще может случиться:

finally 
      { 
       cntx.Database.Connection.Close(); 
       transaction.Dispose(); 
      } 

его известная «ошибка» вы можете найти больше здесь:

http://petermeinl.wordpress.com/2011/03/13/avoiding-unwanted-escalation-to-distributed-transactions/

+0

Вы говорите, что иногда EF 5 оставляет соединение открытым? Таким образом, может открыться более одного соединения с помощью следующего? используя (DataContex dc = new DataContext()) {// несколько выборок, обновлений, удалений, вставок} – andrewramka

+0

MaG3Stican был в значительной степени прав.Я задал этот вопрос http://stackoverflow.com/questions/18278994/transaction-escalated-to-dtc-no-multiple-connections, после чего кто-то указал мне на детали, http://www.digitallycreated.net/Blog/48/entity-framework-transactioncope-and-msdtc, которые в конечном итоге ответили на мой вопрос. – andrewramka

+0

Каждый раз, когда вы выбираете или обновляете EF5, открывается соединение, иногда может закрывать его или иногда его можно открыть, пока контекст еще жив. –

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