如何删除存储库中的代码冗余

How to remove code redundancy in repositories

目前我的数据库中有 2 个表。膳食和 Tables(这是 restau运行t 管理应用程序)。我已经为两个表创建了存储库接口及其实现(授权用户应该能够 add/remove/update 膳食和表格数据,例如菜单中出现新餐时)。 问题是我的两个接口都具有基本相同的方法,我相信这会导致代码冗余。这些是我的界面:

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);
}

我尝试使用 FindAll、FindById、Add、Remove、Update 等常用方法创建基本存储库接口,但我 运行 遇到了我正在处理的问题,并且 return 处理了不同的类型,例如对于 Add 方法,我根据界面选择 return Table 对象或 Meal 对象。我尝试使用对象方法:

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

然后我只需要 IMealsRepository : IRepository 和 ITablesRepository : IRepository 并添加这些存储库独有的其他方法,例如按名称搜索 Meal。我的用餐界面如下所示:

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

我还为那些唯一能够访问存储库的存储库和 return 使用存储库方法的特定类型的对象提供服务。这是一个好方法,还是我在这个项目中关于我的存储库接口的问题太深入了?

您可以按照此 link 来实现 Generic/Base 存储库(如果您不使用实体 Framework/SQL,仍然有效)。

除了 Base/Generic 存储库模式之外,您还需要考虑一些事情

  1. 当您在多个存储库中进行操作以维护事务时,请使用 UnitOfWork 模式。

  2. 不要为每个 table/domain 对象创建存储库。仅为聚合对象创建存储库(电子商务上下文中的示例是 Order 而不是 OrderDetail)。

  3. 如果不需要,请不要创建 table/domain 特定的存储库。如果您正在执行简单的 CRUD 操作并且所有类型的操作都已在我的基本存储库中可用,那么您不需要 table-特定的存储库

    public class 广告服务:IAdvertisementService { 私人只读 IBaseRepository imageRepository;

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

Startup.cs

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

在上面的示例中,我没有创建任何“AdvertisementImage”存储库。

此类问题可以通过 .NET 泛型解决。泛型允许你创建像 RepositoryBase<T> 这样的 class 和像 IRepository<T>

这样的接口

"T"是您在继承class或实现接口中指定的对象类型。

使用泛型,您可以创建如下接口:

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

或者像这样的基础class:

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
}

Internet 上有很多关于泛型的信息,但我很确定泛型是您想要在这种情况下使用的。