How to use Simple injector, Repository and Context - code first
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.
Related videos on Youtube
jony89
Updated on August 28, 2022Comments
-
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 over 10 yearsThanks, 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 over 10 yearsHaving 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 over 10 yearsas 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 ofPASContext
is pass to theEFRepository
constructor.. and when the database will be created ? as this is code-first program. -
Steven over 10 yearsIf 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 over 10 yearsand if i want it in my BLL layer ? if you can, please answer my other questions also in the last comment. Thanks.
-
Steven over 10 yearsWhen 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 over 10 yearsHow 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 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 about 10 years@ShawnMclean: Take a look at this thread.
-
Shawn Mclean about 10 yearsThanks @Steven, that was me posting the question btw
-
Steven about 10 years@ShawnMclean Oh, haha.. I clesrly didn't pay attention :-)
-
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 bySomeService
that expectsFooContext
directly. The services and context do not have interfaces. SimpleInjector spits runtime errors regarding short circuited dependency and ambiguous lifestyles, sayingFooContext
is a transient andDbContext
a web request. Why transient? Different enough for a new question? -
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 over 7 years@Steven: Thank you. You can find it here - stackoverflow.com/q/41599706/146610