组合包含实体框架

问题描述:

我通常使用通用资源库对我的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); 

像以前一样工作。

+0

太棒了!这看起来就像我正在寻找的那样。谢谢! – 2013-02-18 12:32:08

+0

顺便说一句我用类似的投影;-) – 2013-02-18 12:36:00

+0

你可能扩大你的答案更接近我目前使用的方法?我迷失了一些翻译。也可以通过一系列包含作为参数吗? – 2013-02-18 13:07:55

为了清晰起见,我添加了基于@ 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);