EF急切地加载过滤的子对象/仅过滤子对象

时间:2016-01-13 16:13:02

标签: c# entity-framework linq

我的EF Poco类结构如下所示,我尝试实现的是获取所有CategoryProducts包括Products和ProductName,但只有ProductNames具有languageid = 1

我不想过滤Root对象。我不需要加载所有产品名称,只需加载带有languageid = 1

的productname

我不知道如何实现这一目标。例如,我尝试了下面的查询

var products =  db.CategoryProduct.Include("Product.ProductName").
Where(p=>p.Product.ProductName.Any(a=>a.LanguageId==1)).ToList();

但是这个过滤了所有具有带有languageid = 1的ProductName的categoryProducts。这不是我想要的,因为所有产品都有5种不同语言的名称。我只是不想急切地为每个产品加载5次,但只有1次加载languageid = 1

public partial class CategoryProduct
{
    [Key]    
  public int ProductId { get; set; }
 public virtual Product Product { get; set; }

}

public partial class Product
{

        public virtual ICollection<ProductName> ProductName { get; set; }

}

public partial class ProductName
{
     public int ProductId { get; set; }
     public int LanguageId { get; set; }
     public string Name { get; set; }

    public virtual Product Product { get; set; }
}

2 个答案:

答案 0 :(得分:1)

这不容易实现,但以下内容可能会这样做:

from cp in db.CategoryProduct.Include(x => x.Product)
from pn in cp.Product.ProductName.Where(x => x.LanguageId == 1).DefaultIfEmpty()
select new {
    Cat = cp,
    Name1 = pn.Name
}

然后你有Cat.Product产品和Name1中的名字。

基本想法是在LEFT JOIN上设置ProductName

答案 1 :(得分:1)

我担心使用急切加载您无法过滤相关实体,除非您以匿名类型或DTO投影查询:

var products = db.CategoryProduct.Include(c=>c.Product.ProductName)
                                 .Select(c=> new CategoryProductDTO()
                                             {
                                               //...
                                               ProductNames= c.Product.ProductName.Where(a=>a.LanguageId==1)
                                             })
                                 .ToList();

如果您不想投影查询并且想要加载特定的相关实体,那么我建议您使用显式加载:

var catproduct =  db.CategoryProduct.Include(c=>c.Product).FirstOrDefault();// This is just an example, select the category product that you need to load the related entities
context.Entry(catproduct.Product) 
        .Collection(b => b.ProductName) 
        .Query() 
        .Where(pn => pn.LanguageId==1) 
        .Load(); 

但恕我直言,第一个变种是要走的路