如何删除存储库中的代码冗余
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 存储库模式之外,您还需要考虑一些事情
当您在多个存储库中进行操作以维护事务时,请使用 UnitOfWork 模式。
不要为每个 table/domain 对象创建存储库。仅为聚合对象创建存储库(电子商务上下文中的示例是 Order
而不是 OrderDetail
)。
如果不需要,请不要创建 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 上有很多关于泛型的信息,但我很确定泛型是您想要在这种情况下使用的。
目前我的数据库中有 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 存储库模式之外,您还需要考虑一些事情
当您在多个存储库中进行操作以维护事务时,请使用 UnitOfWork 模式。
不要为每个 table/domain 对象创建存储库。仅为聚合对象创建存储库(电子商务上下文中的示例是
Order
而不是OrderDetail
)。如果不需要,请不要创建 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 上有很多关于泛型的信息,但我很确定泛型是您想要在这种情况下使用的。