EF包括不工作.选择新对象时缺少数据

本文关键字:数据 对象 工作 包括不 选择 新对象 EF | 更新日期: 2023-09-27 18:14:54

我想我误解了EF include或延迟加载,或者我没有正确设置我的实体。

如果我有这个查询,它按预期工作。我得到一个带有相关productopoptions的产品列表

var prodQuery = db.Products
    .Include("ProductOptions")
    .AsNoTracking()
    .Where(p =>
       p.CategoryId == category.Id
       && p.Active && !p.Deleted
       && p.ProductOptions.Any(po => po.Active && !po.Deleted)
    ).ToList();

然而,当我试图选择他们到DTO的…产品不包含productopoptions。不知为什么它们没有被包含

 var products = db.Products
    .Include("ProductOptions")
    .AsNoTracking()
    .Where(p =>
       p.CategoryId == category.Id
       && p.Active && !p.Deleted
       && p.ProductOptions.Any(po => po.Active && !po.Deleted))
    .Select(p =>
       new ProductDTO
       {
           Id = p.Id,
           Name = p.Name,
           Description = p.Description,
           ProductOptionDTOs = p.ProductOptions
               .Where(po => po.Active && !po.Deleted)
               .Select(po =>
                   new ProductOptionDTO
                   {
                       Id = po.Id,
                       Name = po.Name,
                       Price = po.Price
                   }
               ).ToList()
       }
    ).ToList();

这是我的实体…删除了不相关的属性

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<ProductOption> ProductOptions { get; set; }
}
public class ProductOption
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ProductId { get; set; }
    public Product Product { get; set; }
}

有人能帮助我理解我在第二个查询中缺少productopoptions吗?

我的错误大家,不再是一个问题。谢谢你的帮助

在调查了每个人的建议并检查了我的代码之后,我发现我在ProductDTO (ProductOptionDTOs属性的声明)中犯了一个错误,它无声地失败并导致ProductOptionDTOs为空而没有错误。

在我测试了EF生成的sql后,我对我的DTO产生了怀疑,并发现sql正确地返回了正确的数据,因此我认为将它映射回DTO一定有问题。

所以事实证明,首先向你们展示我的DTO是至关重要的尽管我拒绝了这个想法

固定:)

EF包括不工作.选择新对象时缺少数据

你有

public ICollection<ProductOption> ProductOptions { get; set; }
ProductOptions = p.ProductOptions
                  .Where(po => po.Active && !po.Deleted)
                  .Select(po =>
                  new ProductOptionDTO
                  {
                      Id = po.Id,
                      Name = po.Name,
                      Price = po.Price
                  }).ToList()

注意与

的区别
new ProductOptionDTO

和类

中productopoptions成员的类型
ICollection<ProductOption>

所以试着改变

public ICollection<ProductOption> ProductOptions { get; set; }
public ICollection<ProductOptionDTO> ProductOptions { get; set; }

并将'ProductOption'类的名称更改为'ProductOptionDTO':

public class ProductOption

public class ProductOptionDTO

你的'Product'类不应该像下面这样改变吗?

public class Product

public class ProductDTO

编辑:尝试这个查询表达式如果只作为一个测试…

var products = (from p in db.Products
               where p.CategoryId == category.Id
               && p.Active && !p.Deleted
               && p.ProductOptions.Any(po => po.Active && !po.Deleted)
               select new ProductDTO
                {
                   Id = p.Id,
                   Name = p.Name,
                   Description = p.Description,
                   ProductOptionDTOs = (from po in p.ProductOptions
                                        where po.Active
                                        && !po.Deleted
                                        select new ProductOptionDTO
                                        {
                                            Id = po.Id,
                                            Name = po.Name,
                                            Price = po.Price
                                        }).ToList() 
                }).ToList()

EDIT2:如果上面不起作用,那么尝试在指定连接属性的地方…

var products = (from p in db.Products
               where p.CategoryId == category.Id
               && p.Active && !p.Deleted
               && p.ProductOptions.Any(po => po.Active && !po.Deleted)
               select new ProductDTO
                {
                   Id = p.Id,
                   Name = p.Name,
                   Description = p.Description,
                   ProductOptionDTOs = (from po in db.ProductOptions
                                        where po.ProductId == p.ProductId
                                        && po.Active
                                        && !po.Deleted
                                        select new ProductOptionDTO
                                        {
                                            Id = po.Id,
                                            Name = po.Name,
                                            Price = po.Price
                                        }).ToList() 
                }).ToList()

问题是Include在执行复杂查询时不起作用。解决这个问题的一种方法是使用所谓的projection。它只是在查询(new {...})中使用的动态类型。

试试这样写:

var products = db.Products
    .AsNoTracking()
    .Where(p =>
        p.CategoryId == category.Id
        && p.Active && !p.Deleted
        && p.ProductOptions.Any(po => po.Active && !po.Deleted))
    .Select(p =>
        new
        {
            product = p,
            options = p.ProductOptions.Where(po => po.Active && !po.Deleted)
        }
    )
    .AsEnumerable()
    .Select(s =>
        new ProductDTO
        {
            Id = s.product.Id,
            Name = s.product.Name,
            Description = s.product.Description,
            ProductOptionDTOs = s.options
                .Select(po =>
                    new ProductOptionDTO
                    {
                        Id = po.Id,
                        Name = po.Name,
                        Price = po.Price
                    }
                )
        }
    );