问题描述 投票:0回答:1

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

我想用 IncludeThenInclude 的谓词(这只是我的愿望)。

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及以上版本,对谓词进行修改?

entity-framework entity-framework-core ef-core-2.0 ef-core-2.2
1个回答
1
投票

即使这样的工作方式不需要将你的逻辑分割到多个仓库参数中,你真的愿意写下

        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))                                                           ;
}
© www.soinside.com 2019 - 2024. All rights reserved.