C# EF急切地加载筛选的子对象/仅筛选子对象

C# EF急切地加载筛选的子对象/仅筛选子对象,c#,entity-framework,linq,C#,Entity Framework,Linq,我的EF Poco类结构如下所示,我试图实现的是获取所有CategoryProducts,包括Products和ProductName,但仅获取languageid=1的ProductNames public partial class CategoryProduct { [Key] public int ProductId { get; set; } public virtual Product Product { get; set; } } public parti

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

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; }
}
我不想过滤根对象。我不需要加载所有产品名称,只需要加载languageid=1的产品名称

我不知道如何做到这一点。例如,我尝试了下面的查询

var products =  db.CategoryProduct.Include("Product.ProductName").
Where(p=>p.Product.ProductName.Any(a=>a.LanguageId==1)).ToList();
但这一个会过滤所有具有languageid=1的ProductName的categoryProducts。这不是我想要的,因为所有产品都有5种不同语言的名称。我只是不想为每个产品加载5次,但对于languageid=1,只加载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; }
}
public分部类CategoryProduct
{
[关键]
public int ProductId{get;set;}
公共虚拟产品产品{get;set;}
}
公共部分类积
{
公共虚拟ICollection ProductName{get;set;}
}
公共部分类ProductName
{
public int ProductId{get;set;}
public int LanguageId{get;set;}
公共字符串名称{get;set;}
公共虚拟产品产品{get;set;}
}

这是不容易做到的,但以下类似的方法可以做到这一点:

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中有名称


基本思想是在
ProductName

上设置
左连接,这并不容易做到,但类似于以下的操作可以做到:

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中有名称


基本思想是在
ProductName

上设置
左连接
,我担心,除非您以匿名类型或以下方式投影查询,否则使用快速加载无法筛选相关实体:

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

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(); 

但是,我认为第一种变体是可行的,我担心使用“急切加载”无法过滤相关实体,除非您以匿名类型或:

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

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(); 

但是我认为第一种变体是可行的,所以你想要的是:所有类别产品,所有产品,但只有那些
languageid=1
?@DrewJordan的产品。不确定是否可能。因此,您需要的是:所有类别产品、所有产品,但仅限于
languageid=1
?@DrewJordan的产品名称。不确定是否可能。显式加载仅对1个元素有效,对集合无效?@batmaci,检查我是否使用产品实例而不是类别作为
Entry
方法的参数。看看这个显式加载只对1个元素有效,对集合无效?@batmaci,检查我是否使用产品实例而不是类别作为
Entry
方法的参数。看看这个