How to use a single instance of DbContext , per request using Unity - asp.net-mvc

I am refactoring a project that creates multiple DbCOntexts per method call in the data repositories.
So I want to have one instance of the DbContext per HTTP request.
I have tried to do:
container.RegisterType<ApplicationDbContext>(new PerRequestLifetimeManager());
and for every repository:
...
container.RegisterType<IBusinessRepository, BusinessRepository>(new InjectionConstructor(new ApplicationDbContext()));
container.RegisterType<ICountryRepository, CountryRepository>();
...
But that will create a new instance of the DbContext() per repository, of course.
I tried
container.RegisterType<IBranchCategoryRepository, BranchCategoryRepository>(
new InjectionConstructor(container.Resolve<ApplicationDbContext>()));
But that gives me:
The PerRequestLifetimeManager can only be used in the context of an
HTTP request. Possible causes for this error are using the lifetime
manager on a non-ASP.NET application, or using it in a thread that is
not associated with the appropriate synchronization context.
So how can I inject the same instance to each repository?

I'm not familiar with Unity, but i am with various other IoC frameworks.
Why are you trying to set what to inject on the repositories?
container.RegisterType<IBusinessRepository, BusinessRepository>(new InjectionConstructor(new ApplicationDbContext()));
Just leave out the DbContext here, but change it to:
container.RegisterType<IBusinessRepository, BusinessRepository>();
Because you did already register this component, it will be automatically injected in the constructor in each class that have a dependency. Your class should then look like this:
public class BusinessRepository : IBusinessRepository
{
private ApplicationDbContext _context;
public BusinessRepository(ApplicationDbContext context)
{
this._context = context
}
}
This works in Castle Windsor.

Related

Using injected DbContext along with DbContext created in Startup.Auth

In Asp.Net MVC, the default template comes with Startup class in Startup.Auth.cs
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
According to the comment in this template, an instance of ApplicationDbContext is created per request.
In my application, I am using the Repository Pattern and inject ApplicationDbContext into the repositories. In my case I am using Ninject, which can share the same context among multiple repositories if needed.
Is there any way to use the same injected ApplicationDbContext in Startup.Auth? Not really sure if this is a good idea to change the default template, at the same time we are creating 2 instances of the same context in 1 request...
In my Ninject code, I am binding ApplicationDbContext to itself as below:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
Not really sure if this a bad practice to bind the context to itself instead of creating an interface? (though it is working fine).
Not really sure if this a bad practice to bind the context to itself
instead of creating an interface?
Registering DbContext as self and per-request lifetime is pretty normal.
I personally like to implement IDbContext interface, so that it is more cleaner to mock when I unit test the repositories. So, my repositories depend on abstraction instead of concrete implementation.
public class ApplicationDbContext : DbContext, IDbContext
{
}
IDbContext
public interface IDbContext
{
DbSet<MyEntity> MyEntities { get; set; }
...
}

Onion architecture : respecting dependencies in the MVC Layer of the application

I am making a website using ASP.NET MVC and an onion architecture. I have the following architecture:
Domain : Entities / Domain Interfaces
Repository : Generic repository (for now) using Entity Framework Code First Approach
Service : Generic Service that calls the Repository
MVC
Now I am trying to create a method in my controller to start testing the methods I have implemented in Repository and Service, and I am having a hard time as to what I am allowed to create in this controller. I want to test a simple Get method in the Repository, but to do that I need GenericService object and GenericRepository object in my controller. To demonstrate what I mean here's a snippet of my GenericRepository(I will skip the interfaces):
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly PrincipalServerContext context;
private DbSet<T> entities;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
}
}
Now my GenericService:
public class GenericService<T> : IGenericService<T> where T : class
{
private IRepository<T> repository;
public GenericService(IRepository<T> repository)
{
this.repository = repository;
}
public T GetEntity(long id)
{
return repository.Get(id);
}
}
And finally, my question, am I allowed to create these objects in my controller as follows (using my dbcontext called PrincipalServerContext):
public class NavigationController : Controller
{
private IGenericService<DomainModelClassHere> domainService;
private IGenericRepository<DomainModelClassHere> domainRepo;
private PrincipalServerContext context;
public ActionResult MyMethod(){
context = new PrincipalServerContext();
domainRepo = new GenericRepository<DomainModelClassHere>(context);
domainService = new GenericService<DomainModelClassHere>(domainRepo);
if(domainService.GetEntity(1)==null)
return View("UserNotFound");//Just as an example
return View();
}
}
Is this allowed? According to Jeffrey Palermo, UI can depend on Service and Domain so I don't know about the Repository. Technically I am not using methods from repository, but I do need to add a reference to the project.
If I can't then how can I create a new GenericService if I don't have a GenericRepository? Is there a better way to instantiate my objects ?
EDIT I think the answer to my question resides in Startup.cs where I can put something like service.addScoped(typeof(IGenericRepository<>),typeof(GenericRepository<>));
but I 'm not sure about this, any ideas?
I'll answer this on my own if ever someone encounters the same problem. There are configuration methods we can use to create instances of classes when needed. In the Startup.cs file you have to add ConfigureServices(IServiceCollection services) method and inside there are several methods that can be applied to services to create these instances. For example you can use:
services.AddTransient(IGenericRepository, GenericRepository)
What is the difference between services.AddTransient, service.AddScope and service.AddSingleton methods in Asp.Net Core 1? (this link explains differences between methods).
AddTransient is good in my case because it creates an instance of an object through the whole lifespan of the application, which is what I need. This means UI is dependant on the rest of the solution, because Startup.cs needs to know about the Repositories as well as the Services.
A pretty good answer can be found here :Onion Architecture : Can UI depend on Domain.

Entity Framework 4.1 Code First - Proper way to share dbContext between repositories?

I'm running into issues with multiple contexts and the main solution that comes up is to share the context between repositories however I haven't found a good example on how to do this.
For reference, I'm using an MVC Web App to connect to my data layer. I'd like to have one context per user request (assuming this is correct).
Thanks,
Edit -
This is my solution with the help of BrokenGlass's links and the following SO Question:
I essentially implemented the Unit Of Work pattern and Dependency Injection. I should have mentioned in addition to using MVC, I'm also using Ninject.
In a given repository constructor (see the link below for Unit Of Work pattern details):
public class PersonRepository : IPersonRepository
{
private readonly MyContext _context;
public PersonRepository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
_context = unitOfWork as MyContext;
}
//...
}
In my MVC App in the NinjectMVC3 class (the key being the InRequestScope() method):
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<MyContext>().InRequestScope();
kernel.Bind<IPersonRepository>().To<PersonRepository>();
//...
}
Your repository layer should provide a unit of work that represents a single request and uses a context object that is then used on all individual repositories that are needed to fulfill the request.
For HTTP / web apps specifically you can cache the db context in the HttpContext.Current.Items which stores shared data for each HTTP request. Also check out this similar SO thread for details: attaching linq to sql datacontext to httpcontext in business layer
My answer to C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories? provides an implementation of a RepositoryProvider that works with a single instance of an ObjectContext. You could use the code the same way, with a LINQ-to-SQL DataContext instead of an EF ObjectContext. The benefit of the RepositoryProvider over Ninject, is that the RepositoryProvider implementation is not bound to a specific DI framework, and can itself be configured in any DI framework.
In addition, you can manage creation and scoping of the DataContext to either a Thread or a WebRequest (such as in #BrokenGlass's answer with HttpContext.Current.Items) by using the DataContextFactory class from here.

How should my ASP.NET MVC Controllers be aware of the repository

I'm trying to get my head around how one would unit test an ASP.NET MVC project that accesses data through a repository of some sort.
During the unit tests I'd obviously want to create a mock repository but how do I pass this mock repository to the Controller instance being tested? Also how would the actual repository, that's really connected to a database, find its way to the controller?
Do I simply do this through the constructors as I've shown below? I think this is how I should set up my controllers, but I'd like some confirmation that this is correct:
public class SampleController : Controller
{
private IRepository _repo;
//Default constructor uses a real repository
// new ConcreteRepo() could also be replaced by some static
// GetRepository() method somewhere so it would be easy to modify
//which concrete IRepository is being used
public SampleController():this(new ConcreteRepo())
{
}
//Unit tests pass in mock repository here
public SampleController(IRepository repo)
{
_repo = repo;
}
}
As everyone has already said, you'll want to use an IoC* or DI** container. But what they haven't said is why this is the case.
The idea is that a DI container will let you bypass ASP.NET MVC's default controller-construction strategy of requiring a parameterless constructor. Thus, you can have your controllers explicitly state their dependencies (as interfaces preferably). How those interfaces map to concrete instances is then the business of the DI container, and is something you will configure in either Global.asax.cs (live) or your test fixture setup (for unit testing).
This means your controller doesn't need to know anything about concrete implementations of its dependencies, and thus we follow the Dependency Inversion Principle: "High-level modules should not depend on low-level modules. Both should depend on abstractions."
For example, if you were to use AutoFac, you would do this:
// In Global.asax.cs's Application_Start
using Autofac;
using Autofac.Integration.Mvc;
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register<IRepository>(() => new ConcreteRepo());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// In your unit test:
var controllerInstance = new SampleController(new InMemoryFakeRepo());
// In SampleController
public class SampleController : Controller
{
private readonly IRepository _repo;
public SampleController(IRepository repo)
{
_repo = repo;
}
// No parameterless constructor! This is good; no accidents waiting to happen!
// No dependency on any particular concrete repo! Excellent!
}
* IoC = inversion of control
** DI = dependency inversion
(the two terms are often used interchangeably, which is not really correct IMO)
Yeah, you're correct, you pass it to your constructor like you have it. By mocking IRepository your explicitly ensuring that the database dependent code doesn't get into the controller for testing, like you want.
When you actually run it, you'll want to setup your application to work with an inversion of control container to enable those dependencies to be injected into your controller (some popular ones are Ninject, StructureMap, and Windsor).
Here's a sample of testing using Moq:
private Mock<IRepository> _mockRepo;
private SampleController _controller;
[TestInit]
public void InitTest()
{
_mockRepo = new Mock<IRepository>();
_controller = new SampleController(_mockRepo.Object);
}
[Test]
public void Some_test()
{
_mockRepo.Setup(mr => mr.SomeRepoCall()).Returns(new ValidObject());
var result = _controller.SomeAction() as ViewResult;
Assert.IsNotNull(result);
}
Now you can test your actions and mock your IRepository to behave however you want.
The best answer I know is to use an Ioc Container:
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
I prefer Castle Windsor
With the controller dependencies passed in you can then create mocks.
We have dependencies that implement interfaces which can be mocked.
For the real one, check out ninject mvc 3 on nuget, for unit testing I prefer to use fake objects with in-memory collections of known data

Can someone explain how Castle Windsor is working in my app?

I have begun using Castle Windsor and somehow my app is all up and running but I dont really understand how its working. Don't refer me to the documentation as I wouldn't be here otherwise.
In my Global.asax.cs I have this:
private static IWindsorContainer container;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
BootstrapContainer();
}
protected void Application_End()
{
container.Dispose();
}
private static void BootstrapContainer()
{
container = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
Now this is registering a new controller factory which I understand. The installation of a WindsorContainer from the current assembly I think registers all installers for example I have a repository installer. I assume that the container that is created in Global.asax is passed to the installers.
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Where(type => type.Name.EndsWith("Repository"))
.WithService.DefaultInterface()
.Configure(c => c.LifeStyle.PerWebRequest));
}
}
In my controller I have created a constructor and passed in a IRepository argument. What I dont understand is how the controller accepts this argument.
Secondly as a test I created 2 repository classes that implement a IRepository. Putting a breakpoint in the controller constructor it passes in one of these classes. How do I map what class that implements IRepository should be passed to the constructor?
I also have Fluent NHibernate up and running. For the next stage I would like the IRepository to have a dependency on the ISession. How do I do that?
Thanks for your help
Since you have registered a controller factory that uses Windsor, it is the Windsor IoC container that is responsible for resolving all your controller instances as and when they are needed.
That is, when you access a URL in your MVC project that points to the action "Index" on your "HomeController" your WindsorControllerFactory will be asked, by the MVC framework, for an instance of HomeController.
If that controller has a constructor which takes an instance of IRepository and you have registered IRepository as a service with the container then Windsor will know how to satisfy the dependency of the HomeController class. Therefore it can first resolve IRepository into some concrete class, instantiate this, and pass it in as a parameter to the HomeController constructor before returning the instance of HomeController to the MVC framework.
If you need different implementations of IRepository for different purposes (i.e. a UserRepository and a ProductRepository) you could create separate interfaces for these, each of which extend IRepository, e.g.:
public interface IProfileRepository : IRepository {}
Then you can use Windsor's fluent registration API to register all concrete classes that implement IRepository, and have them registered by the specific service they provide, e.g. IProfileRepository.
If you do this, Windsor will automatically resolve all instances that implement IRepository for you without you having to write any new registration code when you add a new implementation.
As for making your repository classes depend on ISession, you can do this in a number of ways. I would recommend not letting them depend directly on a session, but rather let them depend on a class through which they can obtain the current session (so that you can share sessions between repositories). There's lots of information on why this is good practice out there on the web, just do a search.
Now, as for actually making it happen, you can either:
Register an instance of a class (by interface) that will retrieve a session for you with Windsor and let Windsor resolve this class as a parameter to your repository constructors.
Register ISession with Windsor and use a factory method to retrieve it when it is resolved.

Resources