Reputation: 155
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?
Upvotes: 1
Views: 138
Reputation: 1654
This type of problem can be solved with .NET Generics. Generics allow you to create classes like RepositoryBase<T>
and interfaces like IRepository<T>
The "T" is the type of an object you specify in the inheriting class or implementing interface.
Using Generics, you could create an interface like this:
public interface IRepository<T>
{
IEnumerable<T> FindAll();
T FindById(int id);
T Add(T newObject);
void Remove(int id);
T Update(T updatedObject);
}
Or a base class like this:
public abstract class RepositoryBase<T, TDto> : IRepository<T>
{
protected IEnumerable<T> FindAll() { // your implementation logic}
protected T FindById(int id) { // your implementation logic
protected T FindByName(string mealName) { // your implementation logic
protected T AddMeal(TDto newMeal) { // your implementation logic
protected void RemoveMeal(int id) { // your implementation logic
protected T UpdateMeal(Meal meal) { // your implementation logic
}
There is lots of information about generics available on the internet but I'm pretty sure Generics is what you want to use in this scenario.
Upvotes: 1
Reputation: 4583
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
Use UnitOfWork pattern when you are doing the operation in multiple repositories to maintain transaction.
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
).
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.
Upvotes: 2