Search code examples
asp.net-mvcentity-frameworksingletonninject

Should I use singleton for DAL and Service classes?


My dal and service classes are as follows. I use Ninject to inject dependencies.

public interface IEntityRepository<T> where T : class, IEntity, new()
{
    ICollection<T> GetAll(Expression<Func<T, bool>> filter = null);
    T Get(Expression<Func<T, bool>> filter);
    T Add(T entity);
    T Update(T entity);
    void Delete(T entity);
}

public class EfEntityRepositoryBase<TEntity, TContext> : IEntityRepository<TEntity>
    where TEntity : class, IEntity, new()
    where TContext : DbContext, new()
{
    public virtual ICollection<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null)
    {
        using (var context = new TContext())
        {
            return (filter == null ? context.Set<TEntity>() : context.Set<TEntity>().Where(filter)).ToList();
        }
    }

    public virtual TEntity Get(Expression<Func<TEntity, bool>> filter)
    {
        using (var context = new TContext())
        {
            return context.Set<TEntity>().SingleOrDefault(filter);
        }
    }

    public virtual TEntity Add(TEntity entity)
    {
        using (var context = new TContext())
        {
            var addedEntity = context.Entry(entity);
            addedEntity.State = EntityState.Added;
            context.SaveChanges();
            return entity;
        }
    }

    public virtual TEntity Update(TEntity entity)
    {
        using (var context = new TContext())
        {
            var updatedEntity = context.Entry(entity);
            updatedEntity.State = EntityState.Modified;
            context.SaveChanges();
            return entity;
        }
    }

    public virtual void Delete(TEntity entity)
    {
        using (var context = new TContext())
        {
            var deletedEntity = context.Entry(entity);
            deletedEntity.State = EntityState.Deleted;
            context.SaveChanges();
        }
    }
}

public interface ICallService
{
}

public class CallManager : ICallService
{
}

public interface ICallDal : IEntityRepository<Call>
{
}

public class EfCallDal : EfEntityRepositoryBase<Call, DatabaseContext>, ICallDal
{
}

public class BusinessModule : NinjectModule
{
    public override void Load()
    {
        Bind<ICallService>().To<CallManager>().InSingletonScope();
        Bind<ICallDal>().To<EfCallDal>();
    }
}

What are the advantages or disadvantages of using Singleton Scope in dal and service classes? Would it be right to use it according to your experience?

I'm also curious about the dependency injection of the DbContext class.

Bind<DbContext>().To<MyContext>().InSingletonScope();

I think using singleton for the context class is risky. Is not it?


Solution

  • What are the advantages or disadvantages of using Singleton Scope in dal and service classes?

    Advantages :

    • you instantiate only one object, gain in CPU and memory.
    • You can share state (which would be a huge disavantage if not controlled)

    Disadvantages :

    • the object graph must be threadsafe (it is not the case of the DbContext)
    • the objects in the object graph must be stateless, unless you want the state being shared by all your objects

    In practice this is not a good idea and it will a big source of problems.

    As you seem to be in a web context (Asp.Net MVC), you should bind most of your objects InRequestScope.

    Avoid using new DbContext. Your context should be bound and injected as constructor argument. Otherwise you miss the point of Dependency injection.

    Once you have understood the mechanics of scoping, you will be able to play with singletons, and scoped factories and the like.