3

Я борюсь с Entityframework в приложении MVC 4, используя Unity for Dependency injection и Automapper для автоматического преобразования объекта в DTO. Я бегу от одной проблемы к другой, EF иногда возвращает старые данные, поэтому я думаю, что мой дизайн недостаточно хорош.Что лучше всего подходит для использования Unity с Entity Framework в приложении MVC 4

Что я имею:

Для настройки Unity я в моем Application_Start:

var UnityContainer = UnityConfig.GetConfiguredContainer(); 
Mapper.Initialize(cfg => cfg.ConstructServicesUsing(type => UnityContainer.Resolve(type))); 
UnityContainer.Resolve<AutoMapperConfig>().MapAutoMapper(); 
... 

В UnityConfig.RegisterTypes:

container.RegisterType<IMyContext, MyContext>(new ContainerControlledLifetimeManager()) 
... 

Мои репозитариев используют инъекции depencency конструктор:

public class MSSQLTenantRepository : IDalTenantRepository 
{ 
    private readonly IMyContext _Db; 
    public MSSQLTenantRepository(IMyContext db) 
    { 
     Db = db; 
    } 
... 

И моя инъекция использовать контроллер конструктора зависимости тоже:

public class TenantController : Controller 
{ 
    private readonly ITenantRepository _TenantRepository; 
    public TenantController(ITenantRepository tenantRepository, 
    { 
     _TenantRepository = tenantRepository; 
    } 
... 

Automapper конфигурация:

public class AutoMapperConfig 
{ 
    private readonly ITenantRepository _TenantRepository; 
    public AutoMapperConfig(ITenantRepository tenantRepository) 
    { 
     _TenantRepository = tenantRepository; 
    } 
... 

Вопросов: иногда я получаю старые данные из первого запроса.

Когда я вручную обновить данные в де сервера SQL, возвращая объект EF в не отражают изменения

Когда я пробовал разные варианты, я также получил ошибку о множественном контексте (из-за Automapper)

Мои вопросы:

  • Что лучше всего использовать Unity, MVC4, EF 6, хранилища и Automapper?
  • Где поставить код (например, в global.asax.c или в UnitiConfig.cs из UnityWebApiActivator
  • Нужно ли мне явно распоряжаться DbContext, и если это так? Где это сделать
?

Существует много говорят об этой теме, но ничего не покрывает все.

+0

Похоже, что вы можете делиться контекстом «не потокобезопасным» ... если вы не хотите полностью управлять контекстом, вы должны использовать подход Unit of Work, как правило, в инструкции Using. –

+0

Это будет работать, когда мое приложение имеет PartialViews? Я боюсь, что либо контроллер располагает контекстом, в то время как другой контроллер нуждается в нем, либо два контекста отслеживают один и тот же объект. Я просмотрел http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns -in-asp-net-mvc-application для возможной реализации. – RHAD

ответ

3

Я понял это с помощью Wiktor.

Во-первых: я должен просто PerRequestLifeTimeManager (как об этом говорит Wiktor Zychla, спасибо за это), который доступен в Unistity для загрузчика MVC.

Второе: Линия:

UnityContainer.Resolve<AutoMapperConfig>().MapAutoMapper(); 

должен быть в Application_BeginRequest (Globas.asax.cs). Я поместил его в Application_Start, так что это было разрешено только при запуске. Входящий запрос создавал новый контекст, поэтому он отличается от того, который использует Automapper. При размещении в BeginRequest решение выполняется по каждому запросу с тем же контекстом, что и репозитории.

+0

Вы все еще в конце концов использовали инструкцию 'Using' с помощью ef dbcontext? Или вам это не нужно? ause «PerRequestLifeTimeManager?» – duyn9uyen

+0

Я не использовал инструкцию using. Насколько я знаю, контекст уничтожается после того, как запрос был полностью обработан. – RHAD

4
container.RegisterType<IMyContext, MyContext>(
    new ContainerControlledLifetimeManager()) 

Это довольно плохо, это делает синглтон из вашего контекста. Таким образом, не только несколько запросов одних и тот же контекст, и вы рискуете параллелизм проблемы, но и потребление памяти такого общего контекста растет без контроля.

Скорее, вы хотели бы иметь время "каждый запрос" жизни, где новый контекст устанавливается для каждого отдельного запроса:

http://www.wiktorzychla.com/2013/03/unity-and-http-per-request-lifetime.html

public class PerRequestLifetimeManager : LifetimeManager 
{ 
    private readonly object key = new object(); 

    public override object GetValue() 
    { 
    if (HttpContext.Current != null && 
     HttpContext.Current.Items.Contains(key)) 
     return HttpContext.Current.Items[key]; 
    else 
     return null; 
    } 

    public override void RemoveValue() 
    { 
    if (HttpContext.Current != null) 
     HttpContext.Current.Items.Remove(key); 
    } 

    public override void SetValue(object newValue) 
    { 
    if (HttpContext.Current != null) 
     HttpContext.Current.Items[key] = newValue; 
    } 
} 

и

container.RegisterType<IMyContext, MyContext>(new PerRequestLifetimeManager()) 

Я не уверен, что делает ваш класс AutoMapperConfig и почему в него вводится репозиторий. Это возможная другая пожизненная проблема, но мне нужно разъяснение.

+1

При реализации PerRequestLifetimeManager (BTW теперь это часть загрузочного устройства Unity (http://www.nuget.org/packages/Unity.Mvc/). Я получаю ошибку при сохранении объекта: «Отношения между двумя объектами не могут определяется, потому что они привязаны к различным объектам ObjectContext ». Причина, по которой automapper для добавления репозитория - попытка решить проблему с ObjectContext. – RHAD

+0

Это еще одна история. Теперь ваше управление жизненным циклом контекста работает правильно, однако вы смешиваете объекты из в разных контекстах (разные запросы). Я предполагаю, что 'AutoMapperConfig', что бы это ни было, по-прежнему подходит к жизни некорректно. Взгляните на мой ответ здесь http://stackoverflow.com/questions/21312428/how-to-identify -dbcontext-in-entity-framework/21312658 # comment32122647_21312658 –

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