我的查询应该返回IQueryable<MyType>
。代码如下所示:
public IQueryable<MyType> GetFooList()
{
var query = (from x in dbContext.TableX
join y in dbContext.TableY on x.our_id equals y.our_id
join z in dbContext.TableZ on y.our_id equals z.our_id
join a in dbContext.TableA on z.other_id equals a.other_id
where !string.IsNullOrEmpty(x.status)
select new
{
(fields....)
})
.AsQueryable();
IQueryable<MyType> result = (IQueryable<MyType>) query;
return result;
}
在调用控制器操作中,我想过滤此列表以查找在运行时指定的值;要筛选的参数在各种调用操作之间会有所不同。 E.g:
List<MyType> FooList = Interface.GetFooList()
.Where( specific conditions )
.ToList();
在行设置result
上,会引发异常:
无效的投射例外未被用户代码
处理无法投射类型的对象 “System.Data.Entity.Infrastructure.DbQuery'1并[d&GT; f__AnonymousType9'9 [System.String,System.Nullable`1 [System.DateTime的],System.String,System.String,System.String,系统。串,System.Int32,System.Nullable'1 [System.DateTime的],System.Nullable'1 [System.DateTime的]]]” 输入'System.Linq.IQueryable'1 [MyType]'。
所以我认为这是一个投射问题,并在调用.Cast<MyType>()
之前添加了AsQueryable()
。这会产生不同的错误:
无法将“匿名类型”类型转换为“MyType”类型。 LINQ to 实体仅支持转换EDM原语或枚举类型。
如果我不进行任何转换,则会在调用操作而不是实体框架访问器中引发这些错误。
我已经尝试了所有链接的“类似问题”中的建议,但无济于事 - 错误不断来回。我甚至尝试包括.Select(obj => new MyType() {fields...} )
以摆脱匿名类型。这也不起作用。
我觉得我错过了一些显而易见的东西。
已编辑添加
我更新了代码以选择类型:select new MyType() {fields...}
。这工作正常。然后调用方法在我过滤结果的行上抛出 NotSupportedException ,并从查询中创建一个列表:
无法在a中构造实体或复杂类型“MyType” LINQ to Entities查询。
ETA2
我将EF表属性复制到一个新类MyTypeDTO。我用MyTypeDTO替换了MyType的所有用法。我收到了这个错误:
LINQ to Entities不支持指定的类型成员'our_id'。仅支持初始化程序,实体成员和实体导航属性。
以下是DTO中的财产:
public int our_id { get; set; }
所以我删除了get / set,rebuilt和reran。不,我得到了同样的错误。
答案 0 :(得分:8)
你是对的,你的所有强制转换失败的原因是匿名类型(即用select new {...}
构造创建的东西)不能转换为命名类型。
我甚至尝试过
.Select(obj => new MyType() {fields...} )
来摆脱匿名类型。这也不起作用。
你走在正确的轨道上 - 这应该有效,假设MyType
有适当的制定者:
var query = from x in dbContext.TableX
join y in dbContext.TableY on x.our_id equals y.our_id
join z in dbContext.TableZ on y.our_id equals z.our_id
join a in dbContext.TableA on z.other_id equals a.other_id
where !string.IsNullOrEmpty(x.status)
select new MyType
{
MyTypeField1 = a.Column1
, MyTypeField2 = z.Column3
, // ...and so on
}; // No need to convert to IQueryable - this should produce the right type
return result;
无法在LINQ to Entities查询中构造实体或复杂类型
'MyType'
。
这是因为MyType
是一个映射实体。您不应该创建返回映射实体的投影,因此EF正确地限制了您执行此操作的能力。您应该能够投影到非映射类型(以创建所谓的DTO - 数据传输对象)。
定义一个类MyTypeDto
,其属性为MyClass
,但没有方法或映射。在方法的定义中使用MyClassDto
。这应该可以解决问题。
答案 1 :(得分:1)
问题非常微妙。 MyType
中不存在查询的匿名类型中的一个字段。我在创建一个用于此方法的视图模型时发现了这一点。
对于它的价值,视图模型工作得很好。例如:
public IQueryable<MyViewModel> GetFooList(int parameter)
{
var query = (from x in dbContext.TableX
join y in dbContext.TableY on x.our_id equals y.our_id
join z in dbContext.TableZ on y.our_id equals z.our_id
join a in dbContext.TableA on z.other_id equals a.other_id
where x.their_id == parameter
select new MyViewModel()
{
field1 = x.field1,
field2 = y.field2,
field3 = z.field3 //<= this field did not exist in MyType
}
).AsQueryable();
return query;
}