2012-05-17 2 views
3

Привет, я использую первый подход Entity Framework 4.1. У меня есть класс MyContainer, который наследует DBContext.Сделка транзакций и DBContext

У меня есть процесс, который имеет 7 шагов на каждом шаге, обращается ко многим методам репозитория (около 60). Этот процесс выполняется автоматически или зависит от бизнес-логики и требований пользователя. Теперь для точки зрения производительности для автоматического процесса я создал контекст, то есть объект MyContainer один раз, и передал его всем методам и удалил его в конце процесса, а его работа прекратилась и улучшила производительность. Но когда этот процесс выполняется, то одни и те же методы выполненный и контейнер создается и размещается в самом методе. например, ниже, но это всего лишь приблизительный код.

public bool UpdateProcess(Process process, MyContainer container = null) 
    { 
     bool disposeContainer = false; 
     if (container == null) 
     { 
      container = new MyContainer(); 
      disposeContainer = true; 
     } 
     var result = SaveProcess(container, process); 
     container.SaveChanges(); 
     if (disposeContainer) 
      container.Dispose(); 
     return result; 
    } 

Для автоматических операций процесса создается в начале процесса и закончился в конце процесса, и для ручной транзакции создаются на BLL в методе, который называется в соответствии с действием пользователя на пользовательском интерфейсе. Теперь предположим, что мой автоматический процесс запущен, и одновременно пользователь сделал какое-то действие по ui. Я получаю исключение. "Transaction (Process ID 65) был заблокирован с блокировкой ресурсов с другим процессом и был выбран «Когда метод UpdateProcess() вызывается вместе как из ручного, так и автоматического процесса, я получить его на контейнере.SaveChanges().

Любая помощь будет принята с благодарностью.

Если я создать область транзакции в этом хранилище метод как

public bool UpdateProcess(Process process, MyContainer container = null) 
{   bool disposeContainer = false;   
      if (container == null) 
      {    
        container = new MyContainer();   
        disposeContainer = true;   
      } 
     using(var trans=new TransactionScop(TransactionScopeOption.RequiresNew))   
     { 
      var result = SaveProcess(container, process); 
      container.SaveChanges(); 
      trans.Complete(); 
     }   
      if (disposeContainer)   
      container.Dispose();   
      return result; 
} 

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

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

+0

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

+2

Я связываю определение [Тупик] (http://en.wikipedia.org/wiki/Deadlock), извинения, если он лишний. –

+0

спасибо за ур усилия bt это не помогает моей проблеме. – ethicallogics

ответ

2

Проблема (sql deadlocking), которую вы имеете, является общей для большинства нетривиальных систем клиент-база данных и может быть очень сложной для решения.

Основным правилом при разработке кода, в котором могут возникать взаимоблокировки, является допущение, что они будут и будут разрабатывать приложение для их надлежащего управления. Обычно это выполняется путем повторной отправки транзакции. Как документировано microsoft here

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

Для того, чтобы свести к минимуму любых тупиков вы видите нормальный подход я беру следующий образом:

  1. Run Profiler с тупиковым графом позволил, чтобы захватить все тупики
  2. Экспорта всех ТУПИК текста и выяснить, почему они происходят
  3. Проверить их можно с помощью табличных подсказок и/или уменьшения уровня изоляции трансакций
  4. Посмотрите, можно ли их минимизировать другими способами, например изменение порядка работы
  5. Наконец, после того, как все это было завершено, убедитесь, что вы пытаетесь захватить блокировки в любое время, когда вы общаетесь с базой данных. & повторно отправьте транзакцию/запрос и т. д.
+0

Спасибо за ваши усилия. Я полностью согласен с тем, что вы ответили, и проследил тупик и все такое. Но проблема в том, что когда я не передаю контейнер из процесса, это означает, что если контейнер создан и размещен в каждом методе репозитория, он отлично работает, но когда я передаю один и тот же контейнер с начала процесса до конца, тогда эта проблема взаимоблокировки возникают. – ethicallogics

+0

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

+0

его операторы обновления в той же таблице. – ethicallogics

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