Repository Pattern pros and cons of each implementation - asp.net-mvc

Hi looking at the repository pattern which commonly seems to be implemented something like:
public class GenericRepository<TEntity> where TEntity : class
{
// other business
public virtual TEntity GetByID(object id)
{
return db.Set().Find(id);
}
public virtual void Insert(TEntity entity)
{
db.Set().Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = db.Set().Find(id);
Delete(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
db.Set().Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
So for every type you want to work with (ie update) you need to instantiate a repository.
So if I had two types I wanted to save Cars and Trucks I would need to go:
var carRepository = new GernericRepository<Car>();
carRepository.Update(myCar);
var truckRepository = new GernericRepository<Truck>();
carRepository.Update(myTruck);
So then you have seperate repositories for each type. To make sure you save everything at once you need the unitOfWork to ensure they all use the same context and save at one time.
Surely wouldn't it be better to have something like:
public class GenericRepository
{
// other business
public virtual TEntity GetByID<TEntity>(object id) where TEntity : class
{
return db.Set<TEntity>().Find(id);
}
public virtual void Insert<TEntity>(TEntity entity) where TEntity : class
{
db.Set<TEntity>().Add(entity);
}
public virtual void Delete<TEntity>(object id) where TEntity : class
{
TEntity entityToDelete = db.Set<TEntity>().Find(id);
Delete(entityToDelete);
}
public virtual void Update<TEntity>(TEntity entityToUpdate) where TEntity : class
{
db.Set<TEntity>().Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
This means the repository only needs to be instantiated once and therefore is truely generic?
So you could update your cars and trucks like this:
var repository = new GernericRepository<Car>();
repository.Update<Car>(myCar);
rRepository.Update<Truck>(myTruck);
Surely this is a better method? Am I missing something? It automatically has only one context too.

The repository pattern does not decouple the data access from the data store, that is what the ETL tool such as NHibernate or the Enity Framework does for. The repository pattern provides reusable methods for extracting data.
I have previously used a so called "Generic" repository as you have described and thought it was great. It isn't until you realise that you have just put another layer on top of NHibernate or the Entity Framework you realise it's all gone Pete Tong.
Ideally what you want are interfaces that describe ways of getting data out of your data store and should not leak what data access you are using. For example:
public interface IEmployee
{
IEmployee GetEmployeeById(Guid employeeId);
IEmployee GetEmployeeByEmployeeNumber(string employeeNumber);
IEnumerable<IEmployee> GetAllEmployeesWithSurname(string surname);
IEnumerable<IEmployee> GetAllEmployeesWithStartDateBetween(DateTime beginDateTime, DateTime endDateTime);
}
This gives you a contract to code to, there is no knowledge of your persistence layer and the queries used to retrieve the data can be unit tested in isolation. The interface could inherit from a base interface that provides common CRUD methods but you would be assuming that all your repositories would need CRUD.
If you go down the road of a Generic Repository you will end up with duplication in your queries and you will find it much harder to unit test the code that uses the repository as you will have to test the queries as well.

Generics by itself does not make an implementation of the repository pattern. We've all seen the generic base class used in example repository pattern implementations but this is to make things DRY (Don't-Repeat-Yourself) by inheriting from the base class ( GenericRepository in your case) to more specialized child classes.
Only using the generic, base class GenericRepository assumes that your repositories will only ever need the most basic CRUD methods. For a more complex system, each repository becomes more specialized based on underlying business entities data requirements.
Also, you will need to have interfaces that define your data contracts with your other layers. Using the repository pattern means you don't want to expose your concrete implementations of your repositories to your other layers.

Related

Ninject factory management

I'm using Ninject.Extensions.Factory to control the lifecycle of the repository layer. I want to have a single point of reference from which I can get a reference to all repositories and have them lazily available. Ninject Factory approach seems like a good solution but I'm not too sure about my solution:
public class PublicUow : IPublicUow
{
private readonly IPublicRepositoriesFactory _publicRepositoriesFactory;
public PublicUow(IPublicRepositoriesFactory publicRepositoriesFactory)
{
_publicRepositoriesFactory = publicRepositoriesFactory;
}
public IContentRepository ContentRepository { get { return _publicRepositoriesFactory.ContentRepository; } }
public ICategoryRepository CategoryRepository { get { return publicRepositoriesFactory.CategoryRepository; } }
}
The problem lies in the PublicRepositories class.
public class PublicRepositoriesFactory : IPublicRepositoriesFactory
{
private readonly IContentRepositoryFactory _contentRepositoryFactory;
private readonly ICategoryRepositoryFactory _categoryRepositoryFactory;
public PublicRepositoriesFactory(IContentRepositoryFactory contentRepositoryFactory, ICategoryRepositoryFactory categoryRepositoryFactory)
{
_contentRepositoryFactory = contentRepositoryFactory;
_categoryRepositoryFactory = categoryRepositoryFactory;
}
public IContentRepository ContentRepository { get { return _contentRepositoryFactory.CreateContentRepository(); } }
public ICategoryRepository CategoryRepository { get { return _categoryRepositoryFactory.CreateCategoryRepository(); } }
}
I'm worried that this will become hard to manage as the number of repositories increases, this class might at some point need to have around 20-30 constructor arguments with the current implementation.
Is there an approach I can take to reduce the number of ctr arguments, like passing an array/dictionary of interfaces or something similar?
I've thought about using property injection in this scenario but most articles suggest avoiding property injection in general.
Is there maybe a more general pattern that would make this easier to manage?
Is this in general a good approach?
It has become rather common practice to use a repository interface like
public interface IRepository
{
T LoadById<T>(Guid id);
void Save<T>(T entity);
....
}
instead of a plethora of specific repositories like IContentRepository, ICategoryRepository,..
specific repositories are only ever useful in case of having specific logic to the entity type and an operation, for example verifying that it's valid. But such operations are rather an "aspect" or a cut-through-concern which you should model as such. Managing/doing validation on save should not be implemented x-times but only once. The only thing you should specifically implement are the exact validation rules (DRY). But these should be implemented in separate classes and used by composition, not inheritance.
Also, for stuff like retrieving an entity or multiple entities "based on a use case", you should use specific query classes, and not put methods on a repository interface (SRP, SOC). An example would be GetProductsByOrder(Guid orderId). This should be neither on the Products nor the Order Repository but rather in a separate class itself.
Taking things a step further, it does not seem a good idea to use a factory to late create all repositories. Why?
makes software more complex (thus harder to maintain and extend)
usually negligible performance gain
deteriorates testability
also see Mark Seeman's blog post Service Locator is an anti pattern, where he's also talking about the disadvantages of late-creation vs. the composition of the entire object graph in one go.
I'm not trying to say that you should never use factory/lazy, but only when you've got a really good reason to :)
Example of a query
I'm not very familiar with EntityFramework. I know NHibernate a whole lot better, so behold.
public class GetParentCategoriesQuery : IGetParentCategoriesQuery
{
private readonly EntityFrameworkContext context;
public GetParentCategories(EntityFrameworkContext context)
{
this.context = context;
}
public IEnumerable<Category> GetParents(Category child)
{
return this.context.Categories.Where(x => x.Children.Contains(child));
}
}
So basically the only thing you change is extracting the GetParentCategoriesQuery into it's own class. The DbContext instance must be shared with the other query and repository instances. For web projects, this is done by binding the DbContext .InRequestScope(). For other applications you may need to use another machanism.
The usage of the query would be quite simple:
public class CategoryController
{
private readonly IRepository repository;
private readonly IGetParentCategoriesQuery getParentCategoriesQuery;
public CategoryController(
IRepository repository,
IGetParentCategoriesQuery getParentCategoriesQuery)
{
this.repository = repository;
this.getParentCategoriesQuery = getParentCategoriesQuery;
}
public void Process(Guid categoryId)
{
Category category = this.repository.LoadById(categoryId);
IEnumerable<Category> parentCategories =
this.getParentCategoriesQuery(category);
// so some stuff...
}
}
An alternative to the scoping is to have the repository instantiate the the query type and pass the DbContext to the query instance (this can be done using the factory extensions):
public TQuery CreateQuery<TQuery>()
{
return this.queryFactory.Create<TQuery>(this.context);
}
which would be used like:
IEnumerable<Category> parents = repository
.CreateQuery<GetParentCategoriesQuery>()
.GetParents(someCategory);
But please note that this alternative will again only late-create the query and thus result in less testability (binding issues may be remain undetected for longer).
The GetParentCategoriesQuery is part of the repository layer, but not part of the repository class.

UnitOfWork - Repository - Service Pattern Advice

So usually when implementing this pattern I have the Service take the Repository<Type> and then have the repository take the UnitOfWork.
I was playing around with hanging a method off the UnitOfWork that gets the Repository<Type> like so:
public class UnitOfWork : IUnitOfWork
{
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Core.Domain.Model.EntityBase<TEntity>
{
return new Repository<TEntity>(this);
}
}
Then the Service would take the UnitOfWork and could resolve the repositories needed from that.
What do you think? Do you see any flaws with this?
I use a similar approach in my ASP.NET MVC program and so far it is working very well.
My IUnitOfWork interface looks like this:
public interface IUnitOfWork
{
IRepository<TEntity> GetRepositoryFor<TEntity>() where TEntity : class;
void SaveChanges();
}
and the associated IRepository interface looks like this:
public interface IRepository<TEntity> : IQueryable<TEntity> where TEntity : class
{
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}
And then pass it to my service like so:
public abstract class BaseService
{
public BaseService(IUnitOfWork unitOfWork)
{
// etc...
}
}
You are right that this makes it easy for the service to resolve it's repositories without having to pass them into the constructor individually which is useful in cases where you might work with multiple repositories in a single service (E.G. Purchase orders and products).
One benefit of using ORM agnostic interfaces like this is that it means you can switch ORMs easily. I'll be honest, the chances of me changing from Entity Framework to another ORM is slim, but the fact is that I could if the need arises. As a bonus my services are much easier to test and I also find this makes my service class cleaner as it is now totally unaware of the ORM in use and is working entirely against the two interface above.
In regards to the comments about a generic repository interface, my advice is to be pragmatic and do what works best for you and your application. There is a number of questions on Stackoverflow on this very topic and the answers to them vary wildly about which is the best way to go (E.G. exposing IQueryable vs IEnumerable, Generic vs non-generic).
I toyed with not having a generic repository as you may already have noticed that my IRepository interface looks like IDbSet; The reason I went for this method is it allows my implementation to handle all of the Entity Framework entity state management stuff that you do with the DbContext E.G.
public void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
EntitySet.Attach(entity);
}
EntitySet.Remove(entity);
}
If I used IDbSet I would need to perform this in my service layer, which would then require a dependency on DbContext which seemed a much more leaky abstraction than my generic repository.

Create a fake DbContext

I am creating an MVC application with EF and currently have used the generic repository pattern, like this one: Generic Repository Pattern. Everything worked great except for the fact that for each repository a new context was created and working with two or more repositories is needed in my application. As I am using StructureMap I added
x.For<IDbContext>().HttpContextScoped().Use(context => new MyContext());
where IDbContext has the respective methods and is no longer generic but is passed through the constructor.
The problem comes when I have to test things - I want to create an in memory storage (faster than db, custom, easy to control data), something like a HashTable or HashSet for example. What I cannot figure out is how to make a fake implementation of IDbContext that retreives the data from that HashTable. For reference IDbContext looks like this (only the methods used by the DbContext in the generic repository):
public interface IDbContext : IDisposable
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
int SaveChanges();
}
In the current situation I suppose I have made a major mistake as creating a fake context does not seem to be a regular routine. Any advices on how to improve the architecture of my application and make it more testable are appreciated.
When I've done this in the past I've generally used a Dictionary to hold my test data something like:
public class FakeDb : IDbContext
{
private Dictionary<Type, Object> _lists = new Dictionary<Type, Object>();
public List<T> GetList<T>()
{
var type = typeof(T);
if(!_lists.Contains(type))
{
_lists.Add(type, new List<T>());
}
return (List<T>)_lists[type];
}
///
}
From a broader perspective I've had a lot of success by wrapping my query building logic up into individual classes rather than repository classes.

How can I inject the Repositories to the UnitOfWork?

I've implemented my UnitOfWork so that it keeps references to all repositories.
public interface IUnitOfWork
{
void Commit();
void RollBack();
}
public interface IMyUnitOfWork : IUnitOfWork
{
IFooRepository Foos { get; }
IBarRepository Bars { get; }
// Other repositories ...
}
Note that the repositories implements a generic type of repository interface.
public interface IFooRepository : IRepository<Entities.Foo>
{
// FooRepository specific methods goes here.
}
public interface IRepository<T> : IRepository
where T : class
{
}
Now how can I inject these repository to my UnitOfWork. Of course I want them with a lazy loading behavior. For example:
public class ConcreteUnitOfWork : IMyUnitOfWork
{
private readonly IUnityContainer unityContainer;
private IFooRepository fooRepository;
public ConcreteUnitOfWork(IUnityContainer unityContainer)
{
this.repositoryFactory = repositoryFactory;
}
public IFooRepository Foos
{
get
{
return this.fooRepository ??
(this.fooRepository = unityContainer.Resolve<IFooRepository>());
}
}
}
I know passing the Unity container to the UnitOfWork is incorrect but what pattern would you offer to solve this issue?
You may mention that I shouldn't keep the repository references in the UnitOfWork but please suppose a service class which needs several repositories. With this design I can just pass the UnitOfWork as the constructor parameter (Constructor Injection) to the service class, but if I didn't keep the repository references in UnitOfWork, I would have to pass all needed repositories as constructor parameters and you know what it leads to.
-- UPDATE --
Please let me know if I'm absolutely wrong and I should never compose the repositories in UnitOfWork. Then please give me a solution about "Constructor Over-injection" here.
-- UPDATE2 --
It seems that composing (referencing to) the repositories from UnitOfWork breaks the Open/Closed principle as we need to change the UnitOfWork class when we add a new repository (add a new property).
If it's right then I should consider a refactoring. Would you please give me some ideas?
It seems as though the current design proposal mixes more than one responsibility into the IMyUnitOfWork interface. You say that this is because otherwise a service class might need to take each Repository independently. I'm assuming you mean something like this:
public MyService(
IUnitOfWork uow,
IFooRepository fooRepository,
IBarRepository barRepository)
This seems to me to be a much simpler and cleaner design.
But then what about Constructor Over-injection?
Well, there's that... but the thing is that this is exactly the same problem you now have with your ConcreteUnitOfWork implementation. You haven't solved the Constructor Over-injection smell at all - you've just moved it to another class.
Actually, by moving it to ConcreteUnitOfWork you've made it more difficult to deal with the situation. Because ConcreteUnitOfWork is a pure infrastructure class (or a support class, if you will) it doesn't have any business context, so it's really hard to suggest a way resolve the Constructor Over-injection smell here.
On the other hand, a given Service (or perhaps a Controller) would tend to be more specialized and have knowledge of the business context, so it wouldn't need every repository in order to do its job - or if it does, it probably attempts to do too much.
Such a specific business component can better be refactored to a Facade Service.

Accessing stored procedures on a code generated DbContext with Entity Framework 4.1 with DDD

I'm working on a large project using ASP.Net MVC 3, EF 4.1 and Ninject for Dependecy Injection. I've read through many of the existing questions here regarding DDD, EF and the Repository Pattern but I can't seem to find anyone incorporating stored procedures with these patterns.
I don't like the idea of implementing yet another repository pattern on top of what seems to already be a UnitOfWork/RepositoryPattern already defined with a DbContext. Also, I generally don't like the idea of creating Service and Repository classes for every type of entity in the system if possible.
The source of my problem stems from this common repository interface which everyone seems to use.
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(Expression<Func<TEntity, bool>> whereClause);
IEnumerable<TEntity> List();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> whereClause);
void Add(TEntity entity);
void Delete(TEntity entity);
// And so on...
}
That's great if all your queries can be in context of a single entity. Where this breaks for me is when I want to access a stored procedure. With EF 4.1 & Code Generatrion you can add stored procedures (e.g. SelectUser) and it will generate a context which looks something like this.
namespace MyCompany.Data.Database
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using MyCompany.Domain.Entities;
using MyCompany.Domain.Contracts;
public partial class MyCompanyEntities : DbContext
{
public MyCompanyEntities()
: base("name=MyCompanyEntities")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Order> Orders { get; set; }
public DbSet<User> Users { get; set; }
public virtual ObjectResult<User> SelectUser(Nullable<int> userId)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int)); MyCompanyEntities x; x.
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", userIdParameter);
}
public virtual ObjectResult<User> SelectUser(Nullable<int> userId, MergeOption mergeOption)
{
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);
var userIdParameter = userId.HasValue ?
new ObjectParameter("UserId", userId) :
new ObjectParameter("UserId", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", mergeOption, userIdParameter);
}
}
}
As part of my DDD setup I have a UserService class and I would like to 'inject' a repository to its constructor. Many examples suggest that the constructor should accept an (IRepository<User> userRepository). This doesn't work for me. Stored procedures are generated on the DbContext class as a method and I am unable to see it.
The only thing I can think of is to either create another interface with the stored procedure methods on it. I don't really want to add it to the generic IRepository because then when you have an instance of IRepository<Order> you'll still see SelectUser which seems a bit odd. Maybe it's not a big deal?
Perhaps I'm going about this the wrong way. Should I not be bothering with creating an interface on top of my DbContext if I'm not trying to create a whole new repository pattern? I was really creating it for the dependency injection. Would it be wrong if the UserService constructor took a MyCompanyEntities instance instead of an interface?
What you found is natural. The problem is that generic repository is insufficient for real scenarios. It is only good for "base" implementation. You need specific repository for User entity which will expose method wrapping call to context exposed stored procedure.

Resources