组合包含实体框架
问题描述:
我通常使用通用资源库对我的EF查询进行样板化,因此我必须编写有限的代码并使用缓存。存储库的源代码可以在here找到。组合包含实体框架
代码中的骨干查询是下面这个。 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>()
方法中的包含列表传递给我,然后我可以在我拨打电话时进行迭代?
答
ofDid你的意思是这样......
IQueryable<T> AnyWithInclude<T,I>(Expression<Func<T,bool>> predicate,
Expression<Func<T,I>> includeInfo)
{
return DbSet<T>.where(predicate).include(includeInfo);
}
通话
Context.YourDbSetReference.AnyWithInclude(t => t.Id==someId, i => i.someNavProp);
在回答问题外作为收藏。
我意识到很晚,物业上出现了超负荷现象。你可以通过一个字符串
这可能会工作,但呼叫并不容易。好吧,我觉得很难。
IQueryable<T> GetListWithInclude<I>(Expression<Func<T, bool>> predicate,
params Expression<Func<T, I>>[] IncludeCollection);
所以我尝试
public virtual IQueryable<T> GetListWithInclude(Expression<Func<T, bool>> predicate,
List<string> includeCollection)
{ var result = EntityDbSet.Where(predicate);
foreach (var incl in includeCollection)
{
result = result.Include(incl);
}
return result;
}
,并呼吁与
var ic = new List<string>();
ic.Add("Membership");
var res = context.DbSte<T>.GetListWithInclude(t=>t.UserName =="fred", ic);
像以前一样工作。
答
为了清晰起见,我添加了基于@ soadyp的答案的解决方案。
public IQueryable<T> Any<T>(Expression<Func<T, bool>> expression = null,
params Expression<Func<T, object>>[] includeCollection)
where T : class, new()
{
IQueryable<T> query = this.context.Set<T>().AsNoTracking().AsQueryable<T>();
if (includeCollection.Any())
{
query = includeCollection.Aggregate(query,
(current, include) => current.Include(include));
}
// Check for a filtering expression and pull all if not.
if (expression != null)
{
query = query.Where<T>(expression);
}
return query.FromCache<T>(expression, includeCollection)
.AsQueryable<T>();
}
用法:
// The second, third, fourth etc parameters are the strongly typed includes.
var posts = this.ReadOnlySession.Any<Post>(p => p.IsDeleted == false,
p => p.Author);
太棒了!这看起来就像我正在寻找的那样。谢谢! – 2013-02-18 12:32:08
顺便说一句我用类似的投影;-) – 2013-02-18 12:36:00
你可能扩大你的答案更接近我目前使用的方法?我迷失了一些翻译。也可以通过一系列包含作为参数吗? – 2013-02-18 13:07:55