这是我的第一个 CRUD 应用程序,我正在尝试确定实现干净架构以访问数据库中当前拥有的 20 多个表的最佳方法。我使用 Dapper 是因为我想发展我的 SQL 技能,但我遇到了如何构建我的服务和存储库层的问题。我知道我可以在各自的接口和实现中编写插入、删除等方法并完成它,但我想使用最佳实践来编写这个应用程序,因此尝试更深入地使用接口。我遇到的问题是,在定义包含 Insert、Get、GetAll 等方法的 IBaseRepository 接口时,我遇到了一个问题,即我的某些存储库不应该有“Delete”或“Update”方法,因为应该有我的情况没有理由编辑或删除审计或日志表中的任何行。
在尝试进行任何更改之前,这是基本存储库的总体轮廓。
public interface ICompanyRepository
{
Task<ICollection<CompanyModel>> GetCompanyModelsAsync();
Task<OperationResult> DeleteCompanyAsync(int companyId);
Task<CompanyModel> GetCompanyModelAsync(int companyId);
Task<OperationResult> UpdateCompanyAsync(CompanyModel companyModel);
}
public class CompanyRepository : ICompanyRepository
{
private readonly IConfiguration _config;
public CompanyRepository(IConfiguration config)
{
_config = config;
}
public async Task<OperationResult> DeleteCompanyAsync(int companyId)
{
using IDbConnection connection = new SqlConnection(_config.GetConnectionString("Default"));
string query = "DELETE FROM Company WHERE Id = @CompanyId";
var parameters = new { CompanyId = companyId };
try
{
int rows = await connection.ExecuteAsync(query, parameters);
if (rows > 0)
{
return OperationResult.Success();
} else
{
return OperationResult.DeleteWithNoRowsEffected();
}
} catch (Exception ex)
{
Log.Error(ex, "Error deleting company {companyId}.", companyId);
return OperationResult.Failure($"An error has occured: {ex.Message}");
}
}
...
为了解决我的问题,我决定制作各种由 IRepository 接口实现的子接口。以下是子界面:
public interface ICreatableTableRepository<T>
{
Task<OperationResult> CreateModelAsync(T model);
}
public interface IDeletableTableRepository<T>
{
Task<OperationResult> DeleteModelAsync(int id);
}
public interface IFetchableTableRepository<T>
{
Task<ICollection<T>> GetModelsAsync();
Task<T> GetModelAsync(int id);
}
public interface IMutableTableRepository<T>
{
Task<OperationResult> UpdateModelAsync(T model);
}
这是我如何在存储库中使用它们的示例,该存储库不应删除或更改行。
public interface ILocationUploadRepository : IFetchableTableRepository<LocationUploadModel>, ICreatableTableRepository<LocationUploadModel>
{
}
一个很好地概述了我的问题并且可能已经遇到过很多次的场景是对仅模拟枚举的静态表执行 CRUD 操作。在这种情况下,定义一个肯定会为可能的每一行产生外键约束异常的删除方法似乎是无意义的。但是,定义 create 方法是非常合理的,因此不适合仅可获取或仅可写的类,而是一个混合类。
我是否在我的代码库中造成不必要的复杂化,或者这有用吗?同样,这是我的第一个应用程序,因此我几乎没有开发完整项目的经验,并且正在寻求反馈。
在这种情况下,定义一个肯定会为可能的每一行产生外键约束异常的删除方法似乎是无意义的
没用。某些实体通常不会创建或删除,这不是存储库问题。如果不删除实体,则任何服务类型都不应该具有执行删除的方法。为了遵循审核实体的示例,日志记录服务将具有 LogEvent() 方法,但没有删除行的方法。
在这种情况下,定义一个肯定会为可能的每一行产生外键约束异常的删除方法似乎是无意义的
并且可能总是存在需要删除的异常操作,例如升级应用程序的过程,对这些枚举执行维护,或修剪旧的审核事件条目。