我的 BaseRespository
是这样的。
public abstract class BaseRespository<TEntity, TContext> : IBaseRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
private readonly TContext _context;
protected BaseRespository(TContext context)
{
_context = context;
}
public async Task<TEntity> GetByCondition(Expression<Func<TEntity, bool>> predicate)
{
return await _context.Set<TEntity>().Where(predicate).FirstOrDefaultAsync();
}
}
而我进入 GetByCondition
这样的方法。
public async Task<Tips> GetTipBySlug(string slug)
{
Expression<Func<Tips, bool>> predicate = (t) => t.Slug == slug &&
t.Status == (int)LU_Status.active &&
t.User.Status == (int)LU_Status.active;
return await _tipRepository.GetByCondition(predicate);
}
我想用 Include
和 ThenInclude
的谓词(这只是我的愿望)。
public async Task<Tips> GetTipBySlug(string slug)
{
Expression<Func<Tips, bool>> whereExpr = (t) => t.Include(t=>t.User).ThenInclude(u=>u.UserImages)
t.Slug == slug &&
t.Status == (int)LU_Status.active &&
t.User.Status == (int)LU_Status.active;
return await _tipRepository.GetByCondition(whereExpr);
}
我如何才能添加所需的 t.Include(t=>t.User).ThenInclude(u=>u.UserImages)
使用EF CORE 2及以上版本,对谓词进行修改?
即使这样的工作方式不需要将你的逻辑分割到多个仓库参数中,你真的愿意写下
Expression<Func<Tips, bool>> whereExpr = (t) => t.Include(t=>t.User).ThenInclude(u=>u.UserImages)
t.Slug == slug &&
t.Status == (int)LU_Status.active &&
t.User.Status == (int)LU_Status.active;
return await _tipRepository.GetByCondition(whereExpr);
在EF的设计使用方式上。
var q = _tipRepository.Set<Tips>()
.Include(t=>t.User)
.ThenInclude(u=>u.UserImages)
.Where(t => t.Status == (int)LU_Status.active)
.Where(t => t.User.Status == (int)LU_Status.active);
return await q.FirstOrDefaultAsync();
为什么你要创建一个 Expression<Func<Tips,bool>>
而不是仅仅 IQueryabe<T>
. 它有 毫无 仓库是否为 "通用",以及 一切 与你想写查询的方式有关。 查询是由 消费者 的。 而不是由仓库或在仓库中(除非你想在不同消费者之间重用一个查询)。
这种设计的疯狂之处在于,它允许repo的消费者指定查询,只是强迫他们通过一个笨拙的、定制的API来实现。 它只是迫使他们通过一个笨拙的、定制的API来完成。
你可以这样写。
public async Task<TEntity> GetByCondition<TEntity>(Expression<Func<TEntity, bool>> predicate, Func<DbSet<TEntity>, IQueryable<TEntity>> baseQuery = null) where TEntity : class
{
IQueryable<TEntity> q = Set<TEntity>();
if (baseQuery != null)
{
q = baseQuery(Set<TEntity>());
}
return await q.Where(predicate).FirstOrDefaultAsync();
}
你不需要用Expression来处理这个问题,因为... Include
是不延时的。 它是一个返回IIncludableQueryable的函数,所以它是一个查询转换函数。
然后。
public async Task<Tips> GetTipBySlug(string slug)
{
Expression<Func<Tips, bool>> whereExpr = (t) => t.Slug == slug &&
t.Status ==1 &&
t.User.Status == 1;
return await GetByCondition(whereExpr, s => s.Include(t => t.User).ThenInclude(u => u.UserImages)) ;
}