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

本文关键字:筛选 对象 加载 EF | 更新日期: 2023-09-27 18:30:13

我的EF Poco类结构如下,我试图实现的是获得所有类别产品,包括产品和ProductName,但只有语言ID为1 的ProductNames

我不想过滤根对象。我不需要加载所有产品名称,只需要加载语言ID为1 的产品名称

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

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

但此项筛选所有具有语言ID为1的ProductName的类别产品。这不是我想要的,因为所有产品都有5种不同语言的名称。我只是不想为每个产品急切地加载5次,但对于语言ID=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; }
}

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

恐怕使用热切加载无法过滤相关实体,除非您将查询投影为匿名类型或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(); 

但是IMHO第一个变体是

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

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上设置一个LEFT JOIN