Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Generic Repository with Dependency Injection [closed]

I have set up my generic repository as follows:

public interface IRepository<T> : IDisposable where T : Entity
{
    T GetById(int id);
}

public abstract class Repository<T> : IRepository<T> where T : Entity
{
    protected readonly SqlDbContext _context = new SqlDbContext();

    public T GetById(int id)
    {
        return _context.Set<T>().Find(id);
    }   
}

To enable dependency injection in my MVC app i also create a Product interface since the signature differs. This is also the case for the other repositories.

public interface IProductRepository : IRepository<Product>
{
    IEnumerable<Product> GetDiscountedProducts();
}

And the implementation (note the inheritance)

public class ProductRepository : Repository<Product>, IProductRepository
{
    public IEnumerable<Product> GetDiscountedProducts()
    {
        return _context.Set<Product>().Where(x=>x)...
    }           
}

Finally the repository gets injected into the MVC controller using unity

public HomeController(IProductRepository repository)
{
}

Is it just me or is this inheritance chain a bit messy here? Is there any way to improve this design?

like image 955
Fixer Avatar asked Sep 19 '11 15:09

Fixer


People also ask

How do I create a generic repository?

To implement generic repository pattern, create two projects - one is an ASP.NET Core Web Application and another is a class library project, which are GR. Web and GR. Data respectively in the solution. The class library is named as SA.

How do I register a generic repository on startup?

You have to register the dependencies in IServiceCollection in startup class. ASP.NET Core supports the constructor Injections to resolve the injected dependencies. Here, register the interface and their implementation into DI, using the add method of different lifetimes.

What is difference between dependency injection and repository pattern?

They really aren't comparable a repository is something you can inject via dependency injection. The aim of DI is to make your application loosely coupled. Rather than specify a concrete implementation you can specify an interface that defines a contract that an implementation must fulfil.


1 Answers

I would suggest to avoid IProductRepository for this particular case (when simply adding single and very specific method) and enhance original IRepository interface as shown below:

public interface IRepository<TEntity> : IDisposable 
                 where TEntity : Entity 
{     
   TEntity GetById(int id); 
   IEnumerable<TEntity> List(IFilterCriteria criteria);
} 

and then implement

public sealed class ProductDiscountFilterCriteria : IFilterCriteria 
{
   // ...
}

but in such case you've to define some logic to transform criteria to an query, it could be a LINQ Expression as you'are already using LINQ. If such creteria expression approach is complex for your case - I would suggest to stick with approach you've proposed.

EDIT: IFilterCriteria is simply Query Object pattern implementation

interface IFilterCriteria<TQuery>
{
   TQuery ToQuery();
}

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<DynamicExpression>
{
  public decimal Discount { get; private set; }

  public DynamicExpression ToQuery()
  {
    // build expression for LINQ clause Where("Discount" > this.Discount)
  }
}

OR raw SQL criteria builder:

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<string>
{
  public decimal Discount { get; private set; }

  public string ToQuery()
  {
    // simplified
    return "WHERE Discount < " + this.Discount;
  }
}

So then you would be able to use it like:

var products = productRepository.List<Product>(
                             new DiscountFilterCriteria { Discount = 50 });

Dynamic LINQ examples and articles:

  • Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)
  • Dynamic LINQ (A little more dynamic)
  • Dynamic LINQ Part 2 (Evolution)
like image 88
sll Avatar answered Sep 27 '22 22:09

sll