我通常使用通用存储库来样板化我的 EF 查询,因此我必须编写有限的代码并使用缓存。可以在此处找到存储库的源代码。
代码中的主干查询是下面的这个。FromCache<T>()
是一种IEnumerable<T>
扩展方法,它HttpContext.Cache
使用 lambda 表达式的字符串化表示作为键来存储查询。
public IQueryable<T> Any<T>(Expression<Func<T, bool>> expression = null)
where T : class, new()
{
// Check for a filtering expression and pull all if not.
if (expression == null)
{
return this.context.Set<T>()
.AsNoTracking()
.FromCache<T>(null)
.AsQueryable();
}
return this.context.Set<T>()
.AsNoTracking<T>()
.Where<T>(expression)
.FromCache<T>(expression)
.AsQueryable<T>();
}
虽然这一切都有效,但由于如果我要编写这样的查询,则相关表会遇到 N+1 问题:
var posts = this.ReadOnlySession.Any<Post>(p => p.IsDeleted == false)
.Include(p => p.Author);
这Include()
对我的查询没有影响,因为它已经运行以便缓存。
现在我知道我可以通过删除导航属性上的虚拟前缀来强制实体框架在我的模型中使用预先加载,但对我来说,这样做是错误的,因为你无法预测你将要进行的查询类型。对我来说,感觉就像我会在控制器类中做的事情。我想知道的是我是否可以将包含列表传递到我的Any<T>()
方法中,然后我可以在调用时进行迭代?