Search code examples
c#interfacepolymorphismredundancy

How to remove code redundancy in repositories


Currently I have 2 tables in my database. Meals and Tables (it's restaurant managing application). I have created repositories interfaces and their implementation for both tables (Authorized user should be able to add/remove/update meals and tables data when for example new meal appears in menu). The problem is that both of my interfaces have basically the same method which causes code redundancy I believe. These are my interfaces:

public interface IMealsRepository
{
    IEnumerable<Meal> FindAll();
    Meal FindById(int id);
    Meal FindByName(string mealName);
    Meal AddMeal(MealDTO newMeal);
    void RemoveMeal(int id);
    Meal UpdateMeal(Meal meal);
}

public interface ITablesRepository
{
    IEnumerable<Table> FindAll();
    Table FindById(int id);
    Table AddTable(Table newTable);
    void RemoveTable(int id);
    Table UpdateTable(Table table);
}

I tried to make a base repository interface with common methods of FindAll, FindById, Add, Remove, Update but I ran into problem that I'm taking and returning different types e.g. for Add method I either return Table object or Meal object depending on the interface. I tried to go with object approach:

public interface IRepository
{
    IEnumerable<object> FindAll();
    object FindById(int id);
    object Add(object newObject);
    void Remove(int id);
    object Update(object updatedObject);
}

Then I would just IMealsRepository : IRepository and ITablesRepository : IRepository and add additional methods unique for those repositories which is for example searching Meal by name. My meals interface would look like this:

public interface IMealsRepository : IRepository
{
    Meal FindByName(string mealName);
}

I also have Services for those Repositories that are the only one able to access repositories and return those particular types of objects using repositories methods. Is that a good approach or I'm going way too deep in this project regarding interfaces of my repositories?


Solution

  • You can follow this link to implement Generic/Base Repository (If you are not using Entity Framework/SQL, still this is valid).

    Other than Base/Generic repository pattern you need to consider a few things

    1. Use UnitOfWork pattern when you are doing the operation in multiple repositories to maintain transaction.

    2. Don't create repository for each table/domain object. Create a repository only for Aggregate object (example in E-Commerce context is Order not for OrderDetail).

    3. Don't create table/domain-specific repository, If you don't need. If you're doing simple CRUD operation and all type of operation already available in my base repository then you don't need a table-specific repository

      public class AdvertisementService : IAdvertisementService { private readonly IBaseRepository imageRepository;

      public AdvertisementService(
          IBaseRepository<AdvertisementImage> imageRepository)
      {
      
          this.imageRepository = imageRepository;
      }
      

    Startup.cs

    builder.Services.AddScoped<IBaseRepository<AdvertisementImage>, BaseRepository<AdvertisementImage>>();
    

    In the above example, I didn't create any `AdvertisementImage' repository.