Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is best practice for using Unity with Entity Framework in a MVC 4 application

I'm struggling with Entityframework in a MVC 4 app, making use of Unity for Dependency injection and Automapper for automapping object to DTO. I run from one issue to the other, EF is sometimes returning old data, so I think my design is not good enough.

What do I have:

To configure Unity I have in my Application_Start:

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

In UnityConfig.RegisterTypes:

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

My respositories use constructor depencency injection:

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

And my controller use constructor dependency injection too:

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

Automapper config:

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

Issues: I sometimes get old data, from the first request.

When I manually update the data in de SQL server, EF's returning object don't reflect the changes

When I tried different options I also got error about multiple context (due to Automapper)

My questions:

  • What is best practice using Unity, MVC4, EF 6, repositories and Automapper?
  • Where to put the code (e.g. in global.asax.c or in UnitiConfig.cs of UnityWebApiActivator?
  • Do I need to explicit dispose the dbcontext, and if so: Where to do this?

There is a lot said about this subject, but nothing covers all.

like image 801
RHAD Avatar asked Jan 12 '23 08:01

RHAD


1 Answers

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

This is rather bad, it makes a singleton out of your context. This way not only multiple requests share the same context and you risk concurrency issues but also the memory consumption of such shared context grows without control.

Rather, you would like to have a "per-request" life time, where a new context is established for each separate request:

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;
  }
}

and

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

I am not sure what your AutoMapperConfig class does and why a repository is injected into it. This is a possible another lifetime issue but I need a clarification on that.

like image 139
Wiktor Zychla Avatar answered Jan 17 '23 13:01

Wiktor Zychla