entity-framework - EF Core 2+ - 使用通用存储库预加载
问题描述
我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);
}
我想将 EF Core 的Include
andThenInclude
与谓词一起使用(这只是我的愿望),如下所示:
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 来完成。
你可以这样写:
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)) ;
}
推荐阅读
- swift - 导航控制器不释放内存,内存泄漏?
- tfs - 如何使用 Visual Studio 2017 在 ASPNET Core 中排除 wwwroot\lib
- reactjs - Codesandbox.io 中的 React-Testing-Library 问题
- selenium - 使用页面对象模式执行操作的多种方式
- javascript - Firestore如何添加到子集合
- azure-resource-manager - Azure 模板中的数组限制为 100 个条目?
- git - Windows 10 上的 git 存储库上的 pip 安装失败
- javascript - 使用 ReactDOM.render 并注入组件的反应不好的做法?
- ios - 推送导航控制器时视图控制器被遮挡
- c++ - 如何根据我出界的一侧执行不同的捕获?