有一个称为产品的实体类型,是由 Entity framework 生成的。我已经写了这个查询
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
下面的代码引发以下错误:
“无法在LINQ to Entities查询中构造实体或复杂类型Shop.Product”
var products = productRepository.GetProducts(1).Tolist();
但是当我使用select p
代替select new Product { Name = p.Name};
它时,它可以正常工作。
如何执行自定义选择部分?
您不能(也应该不能)投影到映射的实体上。但是,您可以投影到匿名类型或DTO上:
public class ProductDTO
{
public string Name { get; set; }
// Other field you may need from the Product entity
}
并且您的方法将返回DTO的列表。
public List<ProductDTO> GetProducts(int categoryID)
{
return (from p in db.Products
where p.CategoryID == categoryID
select new ProductDTO { Name = p.Name }).ToList();
}
我不明白为什么我不应该这样做...这将非常有用...
好吧,EF中的映射实体基本上代表数据库表。如果投影到映射的实体,则基本上要做的是部分加载一个实体,这不是有效状态。EF没有任何线索,例如将来如何处理此类实体的更新(默认行为可能是使用null或对象中包含的任何内容覆盖未加载的字段)。这将是危险的操作,因为您可能会丢失数据库中的某些数据,因此不允许在EF中部分加载实体(或将项目投影到映射的实体)。
@Yakimych很有用,除非您有一些通过查询生成/创建的聚合实体,因此完全了解/打算创建一个全新的实体,然后您将对其进行操作并随后添加。在这种情况下,您要么必须强制运行查询,要么将其推入dto并返回到要添加的实体-这令人沮丧
@Cargowire-我同意,这种情况是存在的,当您知道自己在做什么,但由于限制而被禁止时,这种情况令人沮丧。但是,如果允许这样做,将会有很多沮丧的开发人员抱怨他们在尝试保存部分加载的实体时丢失了数据。IMO,一个会引起很多噪音(引发异常等)的错误比会导致难以跟踪和解释的隐藏错误的行为要好(在开始注意到丢失的数据之前,这些工作很好)。
DTO- 数据传输对象