我认为我误解了有关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也是至关重要的
修正:)
答案 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
}
)
}
);