I\'m new to Entity Framework and joined a project that uses a generic repository as shown below. Are there any disadvantages to the way the repository is set up? I\'ve notic
The main disadvantage of using a generic repository instead of having a concrete repository implementation per Aggregate root, is that you cannot create specific methods for specific usages.
Having all your repositories inherit from a base repository let you create methods like: GetProductsInsSock()
or things like UpdateOnlyProductsThatSatisfySomething()
.
But some workarounds are available! ;-)
Keep on using your generic repository if it suits to your team, the only thing you might have to add is a method that accept a Specification
as parameter. As Eric Evans and Martin Fowler say:
The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against.
In your case it could work as a filter to retrieve the right entities without having the need to create a specific method.
You could simply add this to your IRepository
interface:
IEnumerable<T> Find(Specification<T> predicate);
The method implementation in your Repository
class would be like this:
public class Repository<T> : IRepository<T> where T : class
{
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
// some code...
public IEnumerable<T> Find(Specification<T> specification)
{
return _dbset.Where(specification.Predicate);
}
// some code...
}
The Specification
class could look like this:
public class Specification<T>
{
public Specification(Expression<System.Func<T, bool>> predicate)
{
_predicate = predicate;
}
internal Expression<System.Func<T, bool>> Predicate
{
get { return _predicate; }
}
private readonly Expression<System.Func<T, bool>> _predicate;
}
A call example:
var specification = ProductSpecification.InStock();
var product = Repository.Find(specification).FirstOrDefault();
And finally, the ProductSpecification
class:
internal static class ActionSpecification
{
internal static Specification<Product> InStock()
{
return new Specification<Product>(p => p.IsInStock == true);
}
}