简体   繁体   中英

IoC, UnitOfWork with Ninject and Entity Framework

Im trying to implement a generic repository to my service classes. But when i try to bind my DbConext in Web layer, i need to reference Entity Framework.

My DbContext

  public partial class SalesDbContext : DbContext, IUnitOfWork
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }

        public DbSet<Activity> Activities { get; set; }

        /// <summary>
        /// Allows saving changes via the IUnitOfWork interface.
        /// </summary>
        void IUnitOfWork.Commit()
        {
            base.SaveChanges();
        } 

My IUnitOfWork

public interface IUnitOfWork
{
    /// <summary>
    /// Saves changes to all objects that have changed within the unit of work.
    /// </summary>
    void Commit();
}

My Repository

public class Repository
{
    protected IUnitOfWork UnitOfWork { get; set; }

    protected SalesDbContext Context
    {
        get { return (SalesDbContext)this.UnitOfWork; }
    }

    public Repository(IUnitOfWork unitOfWork)
    {
        if (unitOfWork == null) throw new ArgumentNullException("unitOfWork");
        this.UnitOfWork = unitOfWork;
    }

    private DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
    {
        return this.Context.Set<TEntity>();
    }

    protected IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
    {
        return this.GetDbSet<TEntity>()
            .AsEnumerable();
    }

    protected virtual void SetEntityState(object entity, EntityState entityState)
    {
        this.Context.Entry(entity).State = entityState;
    }
}

And last my Ninject config

private static void RegisterServices(IKernel kernel)
{
    IUnitOfWork unitOfWork = new SalesDbContext();

    kernel.Bind<IUnitOfWork>().ToConstant(unitOfWork);
    kernel.Bind<IMarketService>().To<MarketService>();
} 

The problem is that Ninject wants the references to Entity Framework, but i dont want to add it here, it belongs to the data layer.

And do you think the ToConstant implementation for DbContext will cause problem?

If you do not want to reference the EntityFramework from the top level (eg web) project, how would you build your application? The top level project needs to have references to all underlying dependencies, so they could be put inside bin folder, in the case of web app .

And definitely it is not Ninject, who wants that reference. It is because you are using classes, that depends on EntityFramework in that project.

There is no problem to have references from the top layer (through middle) to the bottom layer. It could be (design) problem, if it would be other way round (eg to have reference from data layer to System.Web ).

UPDATE

As OP stated in his comment. There is one possible solution to avoid referencing dependencies of the bottom layer (like EF) from the top layer using the ninject.extensions.xml . It will work only if the intention was to make ninject configuration in the top layer project, but the project itself is not referencing (using) any of the bottom layer classes with dependencies. Also the EF have to be in GAC.


It is not a good conception to bind your DbContext ToConstant() as long as it implements IDisposable . DbContext should be bound in the shortest possible Scope meaningful for the application (eg InRequestScope() for web app). Ninject will dispose it at the end of the Scope .

If you let DbContext bound ToConstant , it will hold one connection to database per whole application lifecycle. You can get into trouble with concurrency issues and the DbContext could become inconsistent, when accessed by multiple threads, because it wont be able to keep up on object synchronization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM