11

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 ?

tereško
  • 58,060
  • 25
  • 98
  • 150
jony89
  • 5,155
  • 3
  • 30
  • 40

1 Answers1

16

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.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • 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 ? – jony89 Dec 15 '13 at 12:41
  • 1
    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 into the controller; there's nothing fancy about that. That just works. – Steven Dec 15 '13 at 12:49
  • as you can see I'm pretty newbie with this . how can i simply "inject" an IRepository 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. – jony89 Dec 15 '13 at 12:56
  • 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. Simple Injector will do the rest. – Steven Dec 15 '13 at 14:07
  • and if i want it in my BLL layer ? if you can, please answer my other questions also in the last comment. Thanks. – jony89 Dec 15 '13 at 14:16
  • 2
    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, Simple Injector will inject an EFRepository 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. – Steven Dec 15 '13 at 21:04
  • 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. – Shawn Mclean Jan 31 '14 at 19:48
  • @ShawnMclean: I've got no experience with OWIN, but I think this deserves its own thread on the [Simple Injector discussion forum](https://simpleinjector.codeplex.com/discussions/create). 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 Feb 01 '14 at 14:37
  • @ShawnMclean: Take a look at [this thread](https://simpleinjector.codeplex.com/workitem/20694). – Steven Feb 01 '14 at 14:57
  • Thanks @Steven, that was me posting the question btw – Shawn Mclean Feb 01 '14 at 20:11
  • @ShawnMclean Oh, haha.. I clesrly didn't pay attention :-) – Steven Feb 01 '14 at 22:19
  • @Steven: Thanks for the blanket registration bit. Similarly, my app has two layering scenarios: (1) simple CRUD controllers use an `IEntityRepository`, 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? – one.beat.consumer Jan 10 '17 at 19:08
  • @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. – Steven Jan 10 '17 at 19:20
  • @Steven: Thank you. You can find it here - http://stackoverflow.com/q/41599706/146610 – one.beat.consumer Jan 11 '17 at 20:02