存在由实体框架生成的称为产品的实体类型 . 我写了这个查询
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};
时,它可以正常工作 .
如何预成型自定义选择部分?
13 回答
您可以使用它并且它应该正常工作 - >在使用select创建新列表之前必须使用
toList
:另一种简单方法:)
如果您正在使用Entity框架,那么尝试从DbContext中删除属性,该属性使用您的复杂模型作为实体我在将多个模型映射到名为Entity的视图模型时遇到同样的问题
从DbContext中删除条目修复了我的错误 .
您可以使用数据传输对象(DTO)来解决此问题 .
这些有点像视图模型,您可以在其中放入所需的属性,您可以在控制器中手动映射它们,也可以使用AutoMapper等第三方解决方案 .
使用DTO,您可以:
使数据可序列化(Json)
摆脱循环引用
通过保留不需要的属性来减少网络流量(viewmodelwise)
使用objectflattening
我今年在学校一直在学习这个,这是一个非常有用的工具 .
为了回应另一个被标记为重复的问题(see here),我根据Soren的答案找到了一个快速简便的解决方案:
注意:此解决方案仅在Task类(此处称为“Incident”)上具有导航属性(外键)时才有效 . 如果您没有,可以使用其他已发布的解决方案和“AsQueryable()” .
只添加AsEnumerable():
您可以将AsEnumerable添加到您的收藏中,如下所示:
您不能(也不应该)投影到映射的实体 . 但是,您可以投影到匿名类型或DTO:
并且您的方法将返回DTO列表 .
在许多情况下,不需要转换 . 想想你想要强类型List的原因,并评估你是否只想要数据,例如,在Web服务中或显示它 . 这种类型并不重要 . 您只需要知道如何阅读它并检查它是否与您定义的匿名类型中定义的属性相同 . 这是最佳场景,导致您不需要实体的所有字段,这就是匿名类型存在的原因 .
一个简单的方法是这样做:
您可以投影到匿名类型,然后从它投射到模型类型
Edit :由于这个问题得到了很多关注,我将会更具体一些 .
你不能直接投射到模型类型(EF限制),所以没有办法解决这个问题 . 唯一的方法是投射到匿名类型(第一次迭代),然后投射到模型类型(第二次迭代) .
另请注意,当您以这种方式部分加载实体时,它们无法更新,因此它们应保持分离状态 .
我从来没有完全理解为什么这是不可能的,并且这个帖子的答案没有给出强有力的理由(主要是关于部分加载的数据) . 在部分加载的状态实体无法更新是正确的,但是,这个实体将被分离,因此不可能意外地尝试保存它们 .
考虑我上面使用的方法:作为结果,我们仍然有一个部分加载的模型实体 . 该实体是分离的 .
考虑这个(希望存在的)可能的代码:
这也可能导致分离的实体列表,因此我们不需要进行两次迭代 . 编译器会很聪明地看到AsNoTracking()已被使用,这将导致分离的实体,因此它可以允许我们这样做 . 但是,如果省略了AsNoTracking(),它可能会抛出与现在抛出相同的异常,警告我们需要对我们想要的结果做出足够的具体说明 .
我找到了另一种方法,你必须构建一个派生自Product类的类并使用它 . 例如:
不确定这是否“允许”,但它确实有效 .
这是一种在不声明aditional类的情况下执行此操作的方法:
但是,仅当您要在单个实体中组合多个实体时才使用此选项 . 上述功能(简单的产品到产品映射)是这样完成的:
如果您正在执行
Linq to Entity
,则无法在查询的select
闭包中使用ClassType
和new
only anonymous types are allowed (new without type)
看看我项目的这个片段
您在
complex properties
中的Select闭包中添加了new keyword
您将收到此错误因为它将转换为sql语句并在SqlServer上执行
所以 when can I use new with types on select closure?
如果你正在处理
LINQ to Object (in memory collection)
,你可以使用它在我执行
ToList
查询后它变成了in memory collection
所以我们可以在select中使用new ClassTypes