Bronzato
Bronzato

Reputation: 9332

Sharing data context by all my repositories using Entity Framework

I have an MVC3 solution where I have 2 repositories & 2 service layers. I also have separate every layer: controller <--> service <--> repository

Previously, in each of my repositories I had a separate data context. I mean I created a new object instance in each repository. I knew this is not the good way.

So I refactored my solution in order to share my data context between my repositories. Below is the skeleton of my solution. I would like your opinion.

public class EntityFrameworkDbContext: DbContext, IUnitOfWork
{
    public DbSet<Project>           Projects            { get; set; }
    public DbSet<Technology>        Technologies        { get; set; }

    public void Save()
    {
        SaveChanges();
    }
}

public interface IUnitOfWork
{
    void Save();
}

The nInject bindings

ninjectKernel.Bind<IUnitOfWork>().To<EntityFrameworkDbContext>().InRequestScope();
ninjectKernel.Bind<IMainRepository>().To<MainRepository>();
ninjectKernel.Bind<IAdminRepository>().To<AdminRepository>();
ninjectKernel.Bind<IMainService>().To<MainService>();
ninjectKernel.Bind<IAdminService>().To<AdminService>();

Controller

public class AdminController : Controller
{
    private IMainService m_MainService;
    private IAdminService m_AdminService;

    public AdminController(IMainService mainService, IAdminService adminService)
    {
        m_MainService = mainService;
        m_AdminService = adminService;
    }
    ...
}

Service

public class MainService : IMainService
{
    private IMainRepository m_Repository;

    public MainService(IMainRepository repository)
    {
        m_Repository = repository;
    }
    ...
}

Repository

public class AdminRepository : IAdminRepository 
{
    private EntityFrameworkDbContext m_Context;

    public AdminRepository(IUnitOfWork unitOfWork)
    {
        if (unitOfWork == null)
            throw new ArgumentNullException("unitOfWork");

        m_Context = unitOfWork as EntityFrameworkDbContext;
    }
    ...
}

As you can see I implement the Unit of Work pattern but I don't know if this is a good approach.

Thanks.

Upvotes: 0

Views: 1765

Answers (1)

Akos Lukacs
Akos Lukacs

Reputation: 2047

Used a similar approach with MVC3 and Linq2SQL, so I guess this should work for Entity Framework too. Just make sure that you tell the fact to other developers, that by default all queries in the same request use the same EF DbContext if not told otherwise.

One remark: You are effectively casting your IUnitOfWork to a EntityFrameworkDbContext type in your Repository, and I guess you couldn't just replace it with another implementation. Is it a good idea to publish to the callers, that you expect IUnitOfWork (that has 1 method), but under the hood your code works only, if you pass an EntityFrameworkDbContext? And I would guess code would fail, if the parameter is not an actual EntityFrameworkDbContext?

If you use that actual EF datacontext, you can pass in an actual EntityFrameworkDbContext instance to all callers using Ninject like this:

//this makes sure all contexts use the same DbContext
ninjectKernel.Bind<EntityFrameworkDbContext>().To<EntityFrameworkDbContext>().InRequestScope();

Upvotes: 1

Related Questions