Appropriate Repository LifeCycle Scope w/ Ninject in MVC - asp.net-mvc

What is the appropriate LifeCycle Scope for a repository and the EF context when using Entity Framework 4 with Ninject in an MVC 3 application?
I've been using the default of InTransientScope, but questioning whether it should be InRequestScope.
public class MyController: Controller
{
private readonly IMyRepo _repo;
public MyController(IMyRepo repo)
{
_repo = repo;
}
public ActionResult Index()
{
var results = _repo.GetStuff();
return View(results);
}
}
Ninject Module:
public class MyServices : NinjectModule
{
public overrride void Load()
{
Bind<IMyRepo>.To<MyRepo>();
Bind<MyContext>.ToSelf();
}
}
MyRepo:
public class MyRepo: IMyRepo
{
private readonly MyContext _context;
public MyRepo(MyContext context)
{
_context = context;
}
public IEnumerable GetStuff()
{
return _context.Entity;//query stuff
}
}

Your repository can be transient scope, however, I would bind the context in request scope. This way all of your repository instances will share the same context. This way you can reap the caching and transactional benefits of an ORM.
The way it works currently in your code is that a new context is created any time you request one. So if your controller first uses a repository and then calls another module that in turn uses a repository. Each of those repositories will have a different instance of the context. So in effect you are now using your ORM simply as a connection manager and SQL generator.
This can also have unintended consequences. Imagine a code like the following:
public ActionResult MyAction(int id)
{
var entity = _repository.Get<Entity>(id);
entity.Prop = "Processing";
_module.DoStuff(id);
}
If the DoStuff method, eventually calls _repository.Get<Entity>(id); again, you will have 2 different copies of your entity that are out of sync.

This depends on a couple of factors.
Do you care about transactions at all? It not that transient scope is ok for you.
Do you care about transactions but think one transaction per web request is ok for you? Then use web scoped.
Are you ok with objects being "cached" in EF's context and don't want a full database refresh if you request the same object twice? Web scope has this side effect.

Related

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.

Dependency injection in MVC + Web API, without interfaces of repository in controller constructor

I am going to use SimpleInjector in MVC.5 application with WebAPI.2
Some methods of MVC controllers will create objects of repositories for CRUD operations.
Common approach on the Internet is a using interface of repository in MVC controller, like:
public class DashboardController : Controller
{
private readonly IDashboardRepository _repository;
public DashboardController (IDashboardRepository repository) {
_repository = repository;
}
[HttpPost]
public JsonData GetInfo()
{
return _repository.GetInfo();
}
...
Similar approach is recommended for WebAPI
However I would not like to pass IDashboardRepository into constructor of controller because of such reasons: I am sure that I will never mock implementation of repository. I do not need separate public interface for repository (current code base has no these interfaces and I'll need to change a lot of files to add them).
My repositories look like:
public class DashboardFunc : BaseFunc
{
public DashboardFunc(IApplicationStateProvider sp) :
base (sp)
{
}
public DashBoardData GetInfo()
{
...
I would like to use such code in controllers of MVC:
public class DashboardController : Controller
{
public DashboardController () {
}
[HttpPost]
public JsonData GetInfo()
{
DashboardFunc dashBoard = Global.MvcContainer.GetInstance<DashboardFunc>();
return Common.ToJson(dashBoard.GetInfo());
}
The same approach I would like for WebAPI controllers. The only difference is
DashboardFunc dashBoard = Global.WebApiContainer.GetInstance();
Is my modification (not using interface of repository in controller) of standard approach OK? Are there any potential issues that can arise in future that can lead architecture change?
Thank you!
Prevent falling back on calling Global.MvcContainer.GetInstance or any other form of Service Location
anti-pattern. There are a lot of downsides to this, even if you don't want to test that code. Downsides of using this are (among others):
You lose the ability for the container to change the given implementation for you; it makes your application less flexible.
You lose the ability for the container to diagnose the complete object graph for you.
You lose the ability to verify the configuration during app start or using an integration test.
You lose the ability to spot all the class's dependencies just by looking at a single line of code (the constructor).
So even when you don't need that interface, I would advice to still use constructor injection and do the following:
public class DashboardController : Controller {
private readonly DashboardFunc dashboard;
public DashboardController(DashboardFunc dashboard) {
this.dashboard = dashboard;
}
[HttpPost]
public JsonData GetInfo() {
return Common.ToJson(this.dashBoard.GetInfo());
}
}

ASP.NET MVC4 repository injection to controller that depends on currently logged user

Let's say I am creating a "TODO list" web application with following features:
have ability to register/login users
each user has it's own TODO list that is independent from other users
So I've created a simple model that has class ToDoItem.
I'd like to use good practices so I created a generic repository that should fetch TODO items from database:
public interface IRepository<T>
{
IQueryable<T> FindAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
void Add(T newEntity);
void Remove(T entity);
T FindById(long id);
}
(implementation is done with EF and code-first approach but that's not important right now)
This repository will be injected into controller that allows user to list, add, remove, edit TODO items. This is done via custom controller factory I've created that uses Ninject DI container to resolve repository interface to concrete implementation.
So the controller looks like this:
public class HomeController : Controller
{
IRepository<ToDoItem> _repository;
public HomeController(IRepository<ToDoItem> repository)
{
_repository = repository;
}
// list all TODO items for this user
[Authorize]
public ActionResult ListItems()
{
var todoItems = _repository.FindAll();
return View(todoItems);
}
}
My question what is the best way to make controller return TODO list only for the currently logged in user? Ideally I'd like to have controller work with repository that is injected and pre-set with the currently logged user. In other words I'd like to avoid this kind of code in action method:
// list all TODO items for this user
[Authorize]
public ActionResult ListItems()
{
var todoItems = _repository.FindAll(User.Identity);
return View(todoItems);
}
I was thinking that possible solution would be to make controller factory somehow know which user is logged so it would initialize concrete repository and set user ID so that controller doesn't have to do that in every action method. Would this be good approach and if so how can I implement it? If not, what are better alternatives?
I would tackle this in one of two ways:
1.
Make the lifestyle of the repository be per web request and take a dependency on the User.Identity such that this can be used inside of the repository methods. e.g.
public class Repository<ToDoItem> : IRepository<ToDoItem>
{
private IIdentity _identity;
// let the container inject the IIdentity into the repository
// (you will need to register a service with
// the container for IIdentity for this)
public Repository(IIdentity identity)
{
_identity = identity;
}
IQueryable<ToDoItem> FindAll()
{
return FromSomeContext().Where(x => x.Username == _identity.Name);
}
// ....
}
Then register a method with Ninject that it can call to resolve an IIdentity for any component that requires it. (You may decide that injecting an IPrincipal is more useful as you can get information about user roles with it too).
kernel.Bind<IIdentity>()
.ToMethod(ctx => HttpContext.Current.User.Identity)
.InRequestScope();
Now, assuming that Ninject is also constructing your controllers for you and you have registered components for the IRepository<T> services that your application requires, The current user IIdentity will be injected into the Repository<ToDoItem> for you by Ninject.
2.
Create an extension method for IRepository<ToDoItem> (or even IRepository<T> if appropriate) that wraps adding the Where() expression for limiting the returned TODO items only to those that are relevant to the current user.
For those, who use Windsor Castle:
container.Register(
...
Component.For<IIdentity>()
.UsingFactoryMethod(() => { return HttpContext.Current.User.Identity; })
.LifeStyle.PerWebRequest,
...);
Note:
Component.For<ICustomer>().Instance(HttpContext.Current.User.Identity)
does not work, because "When you register an existing instance, even if you specify a lifestyle it will be ignored.", see Windsor Castle Documentation

EF Context Management

What is the best way to manage the context of Entity Framework when using MVC application?
I am using a Repository/Service pattern.
Edit
After looking through some of these questions: stackoverflow.com/users/587920/sam-striano, I am more confused then before. Some say use the context per repository, but wht if I want to use multiple repositories in one controller method?
And to follow good separation design, how do you use UnitOfWork in the MVC app with out making it dependent on EF? I want to be able to unit test my controllers, model, services, etc. using a mock context?
Use a Dependency Injector/Inversion of Control framework like:
Ninject
Autofac
StructureMap
Unity
Using an IoC container, you can tell it how to manage a single data context (most commonly, per request). When you set the data context to per request, the container will auto-magically give any class that needs a data context the same data context per request.
Here is a good article on setting up Ninject.
What your code will most likely end up looking like, assuming you're using a generic repository:
Ninject Module:
public class NinjectRegistrationModule : NinjectModule
{
public override void Load()
{
Bind<MyDataContext>().ToSelf().InRequestScope();
Bind(typeof(RepositoryImplementation<>)).ToSelf().InRequestScope();
}
}
Generic Repository:
public RepositoryImplementation<T> : IRepository<T> where T : class
{
MyDataContext _dataContext;
public RepositoryImplementation<T>(MyDataContext dataContext)
{
_dataContext = dataContext;
}
// bunch of methods that utilize _dataContext
}
Service Class:
public class MyServiceClass
{
IRepository<SomeEntity> _someEntityRepository;
public MyServiceClass(IRepository<SomeEntity> someEntityRepository)
{
_someEntityRepository = someEntityRepository;
}
// do stuff with _someEntityRepository = someEntityRepository;
}
Controller:
public class MyController
{
MyServiceClass _myServiceClass;
public MyController(MyServiceClass myServiceClass)
{
// Ninject will auto-magically give us a myServiceClass
// which will Ninject will inject a repository into MyServiceClass's constructor
_myServiceClass = myServiceClass;
}
public ActionResult MyAction()
{
// use _myServiceClass to do stuff
return View();
}
}
If your functionality is straight forward, then you should create a new ObjectContext in each Repository. They are cheap to instantiate.
If this creates a conflict, you can use a Unit of Work pattern as was suggested in the comment.
I would advise that you be extremely cautious when integrating an ObjectContext or DataContext with a DI container. Many do not use the appropriate scope for their life cycle by default.

Where does my CRUD LINQ Code Go? ASP.NET MVC

I am currently using the ASP.NET MVC framework on a project (pretty much my first time)
I am using Linq2SQL as my data model..
Where should i have this kind of code:
var entries = from e in db.sometable select e;
I currently have this kinda code in the controller and pass the data i get into the view..
is this ok?
if not how do i entend my linq2sql datamodel to include this kindof code?
Thanks
Daniel
To add what #Poco said, here's an example:
In Foo.Common.Repositories (inside the Foo.Common Project):
public interface IRepository<T>
{
IEnumerable<T> GetAll();
void Update(T entity);
void Add(T entity);
void Delete(T entity);
void Save();
}
public interface IUserRepository : IRepository<User>
{
void GetByCredentials(string username, string password);
}
The inside Foo.Data.Repositories (inside Foo.Data project):
public class UserRepository
{
// ... other methods/properties snipped.
public IEnumerable<User> GetAll()
{
// Where this.Users would be L2Sql or Code-First... or some other ORM.
return from u in this.Users orderby u.Name select u;
}
}
Then inside your actual Foo.Web:
public class UserController : Controller
{
private readonly IUserRepository userRepository;
public UserController(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult List()
{
var users = this.userRepository.GetAll();
return this.View(users);
}
}
And inside your Global.asax you'd have Ninject or some other IoC container to resolve IUserRepository:
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserRepository>().To<UserRepository>();
}
protected void Application_Start()
{
var kernel = new StandardKernel();
AreaRegistration.RegisterAllAreas();
MvcApplication.RegisterGlobalFilters(GlobalFilters.Filters);
MvcApplication.RegisterRoutes(RouteTable.Routes);
MvcApplication.RegisterServices(kernel);
// I'm using MVC3 here:
DependencyResolver.SetResolver(new NinjectResolver(kernel));
}
It's common to use the Repository pattern for MVC.
Typically, you define an interface, for instance, IProducts, and then, you implement this interface, calling you linq2sql code. Your controller will accept this interface as a parameter for the constructor, so that it depends on this interface, and not on a concrete class. Using a dependency injector, such as Ninject, will allow you to supply a concrete interface implementation to the constructor. This enables Unit Testing on you web app, and also adds flexibility.
There's a really nice book, Pro ASP.NET MVC 2 Framework, that explains all that. I'm currently reading it, and I just love it.
Here's an example of how to implement the repository pattern
In addition to this I would implement an additional layer to handle your applications business logic and keep your controllers lightweight
It's fine to have Linq queries in controller methods.
If we're talking about separation of concerns, the idea is that your data layer (in this case, the repository(?) code that supplies you with db.sometable) decouples your logic code (controller methods in this case) from the datastore.
You query the data layer rather than the database, so you can change the underlying datastore and your controller code will still work.
Some would argue that it's better again to move as much logic code as you can out of the controllers and into your model code (see the first answer here), but it depends how far you want to go.

Resources