尝试返回IQueryable <MyType>时出现错误

Cod*_*mer 6 c# linq asp.net-mvc entity-framework casting

我有一个应该返回的查询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;
}
Run Code Online (Sandbox Code Playgroud)

在调用控制器操作中,我想过滤此列表以查找在运行时指定的值; 要筛选的参数在各种调用操作之间会有所不同.例如:

List<MyType> FooList = Interface.GetFooList()
    .Where( specific conditions )
    .ToList();
Run Code Online (Sandbox Code Playgroud)

在行设置上result,会引发异常:

用户代码未处理无效的Cast Exception

无法转换类型为'System.Data.Entity.Infrastructure.DbQuery'1 [<> f__AnonymousType9'9 [System.String,System.Nullable .1 [System.DateTime],System.String,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 Entities仅支持转换EDM原语或枚举类型.

如果我不进行任何转换,则会在调用操作而不是实体框架访问器中引发这些错误.

我已经尝试了所有链接的"类似问题"中的建议,但无济于事 - 错误不断来回.我甚至试图.Select(obj => new MyType() {fields...} )摆脱匿名类型.那也行不通.

我觉得我错过了一些明显的东西.

编辑添加

我更新了代码以选择类型:select new MyType() {fields...}.这工作正常.然后调用方法在我过滤结果的行上抛出NotSupportedException,并从查询中创建一个列表:

无法在LINQ to Entities查询中构造实体或复杂类型"MyType".

ETA2

我将EF表属性复制到一个新类MyTypeDTO.我用MyTypeDTO替换了MyType的所有用法.我收到了这个错误:

LINQ to Entities不支持指定的类型成员'our_id'.仅支持初始值设定项,实体成员和实体导航属性.

这是DTO的财产:

public int our_id { get; set; }
Run Code Online (Sandbox Code Playgroud)

所以我删除了get/set,rebuilt和reran.不,我得到了同样的错误.

das*_*ght 9

你是对的,你的所有强制转换失败的原因是匿名类型(即你用select new {...}构造创建的东西)不能被强制转换为命名类型.

我甚至试图.Select(obj => new MyType() {fields...} )摆脱匿名类型.那也行不通.

你是在正确的轨道 - 这应该工作,假设MyType有适当的setter:

 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;
Run Code Online (Sandbox Code Playgroud)

'MyType'无法在LINQ to Entities查询中构造实体或复杂类型.

这是因为MyType是映射的实体.您不应该创建返回映射实体的投影,因此EF正确地限制了您执行此操作的能力.您应该能够投影到非映射类型(以创建所谓的DTO - 数据传输对象).

定义一个MyTypeDto具有属性MyClass但没有方法或映射的类.用于MyClassDto方法的定义.这应该可以解决问题.


Cod*_*mer 3

这个问题非常微妙。查询的匿名类型中的字段之一不存在于 中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;
}
Run Code Online (Sandbox Code Playgroud)