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

时间:2015-09-28 11:03:22

标签: c# entity-framework linq-to-entities

我认为我误解了有关EF包含或延迟加载的内容,或者我没有正确设置我的实体。

如果我有这个查询,它会按预期工作。我得到了一个包含相关productOptions的产品列表

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时...产品不包含ProductOptions。不知怎的,他们没有被包括在内

 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; }
}

有人可以帮我理解我在第二次查询中缺少ProductOptions吗?

我的错误是每个人,不再是问题。感谢您的帮助

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

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

事实证明,即使我驳回了这个想法,向我们展示我的DTO也是至关重要的

修正:)

2 个答案:

答案 0 :(得分:1)

你有

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

以及类中的ProductOptions成员的类型

ICollection<ProductOption>

所以尝试更改

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

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

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

public class ProductOption

public class ProductOptionDTO

也不应该更改“产品”类如下?

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

答案 1 :(得分:1)

问题是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
                    }
                )
        }
    );