Entity framework 如果继承,则在非EDM基类型中定义的属性上有条件地添加查询运算符

Entity framework 如果继承,则在非EDM基类型中定义的属性上有条件地添加查询运算符,entity-framework,generics,inheritance,Entity Framework,Generics,Inheritance,(问题末尾的C#代码) 我有以下继承链: PreRecord <- Record <- (multiple entity types) 如果参数约束为Record,则应用使用ID属性的查询运算符不会有问题。我如何使用不同的(缩小)通用约束mid方法并仍然返回IQueryable(of T)/IQueryable,其中T仍然被约束为预记录 我试过这个: 'Sample 2 qry = dcx.Set(Of T).Cast(Of Record).OrderBy(Function(x)

(问题末尾的C#代码)

我有以下继承链:

PreRecord <- Record <- (multiple entity types)
如果参数约束为
Record
,则应用使用
ID
属性的查询运算符不会有问题。我如何使用不同的(缩小)通用约束mid方法并仍然返回
IQueryable(of T)
/
IQueryable
,其中
T
仍然被约束为
预记录


我试过这个:

'Sample 2
qry = dcx.Set(Of T).Cast(Of Record).OrderBy(Function(x) x.ID).Cast(Of PreRecord)()
这不起作用:

//Sample 2
qry = dcx.Set<T>.Cast<Record>.OrderBy(x => x.ID).Cast<PreRecord>()
LINQ to实体仅支持强制转换EDM基元或枚举类型


C#等效物:

//Sample 1
public IQueryable<T> GetQuery<T>(T row) where T : PreRecord {
    var dcx = new MyDbContext();
    var qry = dcx.Set<T>.AsQueryable();
    if (row is RecordBase) {
        //modify/rewrite the query here
    }
    return qry;
}
//示例1
公共IQueryable GetQuery(T行),其中T:预记录{
var dcx=new MyDbContext();
var qry=dcx.Set.AsQueryable();
if(行为记录库){
//在此处修改/重写查询
}
返回qry;
}
但这不起作用:

//Sample 2
qry = dcx.Set<T>.Cast<Record>.OrderBy(x => x.ID).Cast<PreRecord>()
//示例2
qry=dcx.Set.Cast.OrderBy(x=>x.ID.Cast())

这里的问题是编译器在编译时检查已经存在的查询,而PreRecord类没有ID属性。我们不能使用simply Cast,因为当在查询解析器的定义中使用它时,解析器会尝试将其转换为sql—但sql中不存在这样的东西。Sql只支持将一种列类型转换为另一种列类型,因此在.NET端,它只支持基本类型和枚举类型。为了克服编译器查询检查,我们可以使用Expression类来构建动态查询:

ParameterExpression e = Expression.Parameter(typeof(Record));
Expression body = Expression.Property(e, "ID");
Expression<Func<PreRecord, int>> orderByExpression = Expression.Lambda<Func<PreRecord, int>>(body, e);
ParameterExpression e=Expression.Parameter(typeof(Record));
表达式体=Expression.Property(e,“ID”);
表达式orderByExpression=Expression.Lambda(body,e);
并在查询中使用您的表达式:

qry = dcx.Set<T>.OrderBy(orderByExpression);
qry=dcx.Set.OrderBy(orderByExpression);

这样,linq查询将不会在编译时验证,而是在执行时验证。这里我假设ID的类型为int,如果类型不同,则相应地更改它。

LINQ to Entities仅支持实体类型。如果要使用自己的类型,则必须计算LINQ to Entities查询,例如,通过调用
ToArray
ToList
,然后使用LINQ to对象。@jmchilney True。但是如果该方法的通用参数约束是
Record
,那么查询
Record
中声明的属性就不会有问题。但是现在该方法的约束是
PreRecord
如何查询
Record
属性?(更新了问题。)