How to use Simple injector, Repository and Context - code first

10,250

Since you will probably have many IReposotory<T> implementations (for Product, Customer, Employee, etc), it's better make a single open generic registration for IRepository<T> like this:

container.Register(typeof(IRepository<>), typeof(EFRepository<>), Lifestyle.Scoped);

Where the scoped lifestyle is defined as:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

This registration ensures that Simple Injector will return a EFRepository<Product>, every time a IRepository<Product> is requested, an EFRepository<Customer> for IRepository<Customer>, and so on, and so on.

Since you want the same DbContext instance to be used over all repositories within the same request, you should also register the DbContext with the scoped Lifestyle:

container.Register<DbContext, PASContext>(Lifestyle.Scoped);

In the BLL i have a class ProductBLL and i want to get all products from the database and pass it to, lets say HomeController

In that scenario, this ProductBLL seems like a useless abstraction to me. If all it does is passing data through, you can as easily let your HomeController depend on IRepository<Product> directly.

Share:
10,250

Related videos on Youtube

jony89
Author by

jony89

Updated on August 28, 2022

Comments

  • jony89
    jony89 over 1 year

    I'm trying to use Simple Injector to create my repository and use it in the Business logic layer ( also i want to use PerWebRequest method ) .

    In the DAL layer i have :

    public interface IRepository<T> where T : class
    {
        void Add(T entity);
        void Delete(T entity);
        void Delete(int id);
        void Update(T entity);
        T GetById(int Id);
        IQueryable<T> All();
        IEnumerable<T> Find(Func<T, bool> predicate);
    }
    

    and :

    public class EFRepository<T> : IRepository<T>, IDisposable where T : class
    {
        #region Members
        protected DbContext Context { get; set; }
        protected DbSet<T> DbSet { get; set; }
        #endregion
    
        #region Constructors
    
        public EFRepository(DbContext dbContext)
        {
            if (dbContext == null)
                throw new ArgumentNullException("dbContext");
            Context = dbContext;
            DbSet = Context.Set<T>();
        }
    

    and my context :

    public class PASContext : DbContext, IDbContext
    {
        public DbSet<Product> Products { get; set; }
        public DbSet<User> Users { get; set; }
    
        public PASContext()
            : base("PostAndSell")
        { }
    }
    

    As you can see EFRepository has only one constructor that takes one argument - this is because i want to use Simple Injector to create an instance of the context and pass it to the repository while it is created .

    In the BLL i have a class ProductBLL and i want to get all products in that class (with some GetAll method) from the database and pass it, lets say to HomeController .

    I really need someone to talk me through this .

    I started by installing the right packages from the nuger (Simple Injector and Simple Injector ASP.NET Integration)

    also in my global.asax.cs file, under Application_Start() function I`ve added :

    var container = new SimpleInjector.Container();
    
    container.RegisterPerWebRequest<IRepository<Product>, EFRepository<Product>>();
    

    but where do i create the Context instance ? and how can i access it in the business layer ?

  • jony89
    jony89 over 10 years
    Thanks, but if i do have some class with logic in the BLL, how can i use the repository ? my concept is that BLL talks to DAL through repositories and MVC talks to BLL through classes like productBLL . Also if i want to access this repository in HomeController how can i do it ? and when EF will create the database ?
  • Steven
    Steven over 10 years
    Having an BLL class is only useful when you actually have any logic. But if you have logic, you will of course need to inject that ProductBLL into your controller instead of the product (or in case the added behavior is solely cross-cutting concerns such as logging, security, validation, etc, you can add this using a decorator on IRepository instead). If you want to access the repo in the controller, you just inject an IRepository<T> into the controller; there's nothing fancy about that. That just works.
  • jony89
    jony89 over 10 years
    as you can see I'm pretty newbie with this . how can i simply "inject" an IRepository<Product> into the controller ? what code is related to the word "inject" ? how can i access the Repostiroy in the productBLL and inject it to the controller - Please show me some code related to this . In addition i still cant see where an instance of PASContext is pass to the EFRepository constructor.. and when the database will be created ? as this is code-first program.
  • Steven
    Steven over 10 years
    If you've installed the MVC Quick Start NuGet, it's just a matter of defining a public constructor on your controller that takes a parameter of type IRepository<Product>. Simple Injector will do the rest.
  • jony89
    jony89 over 10 years
    and if i want it in my BLL layer ? if you can, please answer my other questions also in the last comment. Thanks.
  • Steven
    Steven over 10 years
    When resolving a type, Simple Injector will inject the dependencies into the constructor of that type. If your HomeController depends on BBLProducts, and you resolve a HomeController, Simple Injector will create a BBLProducts for you. If BBLProducts depends on IRepository<Product>, Simple Injector will inject an EFRepository<Product> into that BBLProducts for you. Simple Injector will build up a complete graph of related objects for you. You only have to resolve the root object, and in the case of MVC, this root object (a controller) is resolved for you.
  • Shawn Mclean
    Shawn Mclean over 10 years
    How do you do this without using PerWebRequest? I'm using OWIN which does not support HttpContext.Current, but I'd like to share the same entity framework context with all repositories.
  • Steven
    Steven about 10 years
    @ShawnMclean: I've got no experience with OWIN, but I think this deserves its own thread on the Simple Injector discussion forum. What's the programming model behind OWIN? Some interesting input for this discussion is the programming model behind OWIN. Is it asynchronous like Web API?
  • Steven
    Steven about 10 years
    @ShawnMclean: Take a look at this thread.
  • Shawn Mclean
    Shawn Mclean about 10 years
    Thanks @Steven, that was me posting the question btw
  • Steven
    Steven about 10 years
    @ShawnMclean Oh, haha.. I clesrly didn't pay attention :-)
  • one.beat.consumer
    one.beat.consumer over 7 years
    @Steven: Thanks for the blanket registration bit. Similarly, my app has two layering scenarios: (1) simple CRUD controllers use an IEntityRepository<T>, and (2) business rich transactions are done by SomeService that expects FooContext directly. The services and context do not have interfaces. SimpleInjector spits runtime errors regarding short circuited dependency and ambiguous lifestyles, saying FooContext is a transient and DbContext a web request. Why transient? Different enough for a new question?
  • Steven
    Steven over 7 years
    @one.beat.consumer that absolutely deserves a new question. Be as specific as possible in your question: show your code, your registrations, the details of the exception message and make sure you read the documentation that the error message points to before posting your question.
  • one.beat.consumer
    one.beat.consumer over 7 years
    @Steven: Thank you. You can find it here - stackoverflow.com/q/41599706/146610