使用存储库模式通用存储库调用存储过程
calling stored procedure using repository pattern generic repository
我正在使用通用存储库与数据库进行通用操作通信,我想添加一个函数来调用存储过程或查询。
我正在尝试在 class 中实现多个泛型,但是当我调用这段代码时,它总是 returns Iqueryable 类型 T,但是,我想使用多个 classes T,T1,T2
RepositoryBase class
public abstract class RepositoryBase<T,T1> : IRepositoryBase<T,T1> where T : class where
T1:class
{
protected RepositoryContext RepositoryContext;
protected DbSet<T> dbSet;
public RepositoryBase(RepositoryContext repositoryContext)
{
RepositoryContext = repositoryContext;
}
public IQueryable<T> FindAll(bool trackChanges) => !trackChanges ?
RepositoryContext.Set<T>()
.AsNoTracking() :
RepositoryContext.Set<T>();
public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression,
bool trackChanges) =>
!trackChanges ?
RepositoryContext.Set<T>()
.Where(expression)
.AsNoTracking() :
RepositoryContext.Set<T>()
.Where(expression);
public void Create(T entity) => RepositoryContext.Set<T>().Add(entity);
public void Update(T entity) => RepositoryContext.Set<T>().Update(entity);
public void Delete(T entity) => RepositoryContext.Set<T>().Remove(entity);
//this is the function i am facing issue
public IQueryable<T> ExecuteSqlQueryOrProcedure(string sql)
{
return RepositoryContext.Set<T>().FromSqlRaw(sql);
}
}
IRepositoryBase 接口
{
IQueryable<T> FindAll(bool trackChanges);
IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression,
bool trackChanges);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> ExecuteSqlQueryOrProcedure(string sql);
}
下面是存储库 class 我在其中调用存储库基本函数..
public class SurveyDashboardRepository : RepositoryBase<SurveyStatistics, SurveyCropTypeWise>, ISurveyDashboardRepository
{
public SurveyDashboardRepository(RepositoryContext repositoryContext) : base(repositoryContext)
{
}
public async Task<IList<SurveyStatistics>> StatisticsAsync(SurveyStatisticsDto dto)
{
var query = $"Exec CN_RPT_SurveyDashBoard @Flag='GTY',@ForTheYear={dto.ForTheYear}";
if (dto.PlantCode.HasValue)
{
query += $",@PlantCode={dto.PlantCode}";
}
return await ExecuteSqlQueryOrProcedure(query).ToListAsync();
}
public async Task<IList<SurveyCropTypeWise>> CropTypeWiseAsync(SurveyCropTypeWiseDto dto)
{
var query = $"Exec CN_RPT_SurveyDashBoard @Flag='CT',@ForTheYear={dto.ForTheYear}";
if (dto.PlantCode.HasValue)
{
query += $",@PlantCode={dto.PlantCode}";
}
//on this line i am getting error
return await ExecuteSqlQueryOrProcedure<SurveyCropTypeWise>(query).ToList<SurveyCropTypeWise>();
}
}
下面是上面仓库的相关接口class
public interface ISurveyDashboardRepository
{
Task<IList<SurveyStatistics>> StatisticsAsync(SurveyStatisticsDto dto);
Task<IList<SurveyCropTypeWise>> CropTypeWiseAsync(SurveyCropTypeWiseDto dto);
}
所以在每个存储库中我将调用几个过程,我不确定如何处理这个问题,非常感谢任何帮助。
您试图让通用存储库做太多事情。在这种情况下,使用它的唯一原因是获得一个可以处理 CRUD 操作的基础 class。
就 IQueryable
而言,这是一个有漏洞的抽象,因为它迫使调用者拥有持久的特定知识,并且违反了 Demeter 法则。因此,它不是一个完整的抽象。如果您真的想遵循存储库模式,请将其删除。
完成这些事情后,您的基础 classes 就简单多了,您在管理多种类型时也不会有问题。
如果您仍然无法使用多个类型定义,请停止为该存储库使用基础 class。没有人说项目中的所有存储库都需要遵循完全相同的模式。在适合的地方应用它,否则它会使您的代码库恶化。
我正在使用通用存储库与数据库进行通用操作通信,我想添加一个函数来调用存储过程或查询。
我正在尝试在 class 中实现多个泛型,但是当我调用这段代码时,它总是 returns Iqueryable 类型 T,但是,我想使用多个 classes T,T1,T2
RepositoryBase class
public abstract class RepositoryBase<T,T1> : IRepositoryBase<T,T1> where T : class where
T1:class
{
protected RepositoryContext RepositoryContext;
protected DbSet<T> dbSet;
public RepositoryBase(RepositoryContext repositoryContext)
{
RepositoryContext = repositoryContext;
}
public IQueryable<T> FindAll(bool trackChanges) => !trackChanges ?
RepositoryContext.Set<T>()
.AsNoTracking() :
RepositoryContext.Set<T>();
public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression,
bool trackChanges) =>
!trackChanges ?
RepositoryContext.Set<T>()
.Where(expression)
.AsNoTracking() :
RepositoryContext.Set<T>()
.Where(expression);
public void Create(T entity) => RepositoryContext.Set<T>().Add(entity);
public void Update(T entity) => RepositoryContext.Set<T>().Update(entity);
public void Delete(T entity) => RepositoryContext.Set<T>().Remove(entity);
//this is the function i am facing issue
public IQueryable<T> ExecuteSqlQueryOrProcedure(string sql)
{
return RepositoryContext.Set<T>().FromSqlRaw(sql);
}
}
IRepositoryBase 接口
{
IQueryable<T> FindAll(bool trackChanges);
IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression,
bool trackChanges);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> ExecuteSqlQueryOrProcedure(string sql);
}
下面是存储库 class 我在其中调用存储库基本函数..
public class SurveyDashboardRepository : RepositoryBase<SurveyStatistics, SurveyCropTypeWise>, ISurveyDashboardRepository
{
public SurveyDashboardRepository(RepositoryContext repositoryContext) : base(repositoryContext)
{
}
public async Task<IList<SurveyStatistics>> StatisticsAsync(SurveyStatisticsDto dto)
{
var query = $"Exec CN_RPT_SurveyDashBoard @Flag='GTY',@ForTheYear={dto.ForTheYear}";
if (dto.PlantCode.HasValue)
{
query += $",@PlantCode={dto.PlantCode}";
}
return await ExecuteSqlQueryOrProcedure(query).ToListAsync();
}
public async Task<IList<SurveyCropTypeWise>> CropTypeWiseAsync(SurveyCropTypeWiseDto dto)
{
var query = $"Exec CN_RPT_SurveyDashBoard @Flag='CT',@ForTheYear={dto.ForTheYear}";
if (dto.PlantCode.HasValue)
{
query += $",@PlantCode={dto.PlantCode}";
}
//on this line i am getting error
return await ExecuteSqlQueryOrProcedure<SurveyCropTypeWise>(query).ToList<SurveyCropTypeWise>();
}
}
下面是上面仓库的相关接口class
public interface ISurveyDashboardRepository
{
Task<IList<SurveyStatistics>> StatisticsAsync(SurveyStatisticsDto dto);
Task<IList<SurveyCropTypeWise>> CropTypeWiseAsync(SurveyCropTypeWiseDto dto);
}
所以在每个存储库中我将调用几个过程,我不确定如何处理这个问题,非常感谢任何帮助。
您试图让通用存储库做太多事情。在这种情况下,使用它的唯一原因是获得一个可以处理 CRUD 操作的基础 class。
就 IQueryable
而言,这是一个有漏洞的抽象,因为它迫使调用者拥有持久的特定知识,并且违反了 Demeter 法则。因此,它不是一个完整的抽象。如果您真的想遵循存储库模式,请将其删除。
完成这些事情后,您的基础 classes 就简单多了,您在管理多种类型时也不会有问题。
如果您仍然无法使用多个类型定义,请停止为该存储库使用基础 class。没有人说项目中的所有存储库都需要遵循完全相同的模式。在适合的地方应用它,否则它会使您的代码库恶化。