【发布时间】:2015-06-17 13:44:20
【问题描述】:
我想对仅在运行时已知的字段进行排序,并且该字段可以在 select 子句中构造。
要求:
- 用户应该能够对任何列进行排序;
- 该列可能来自实体或投影类;
- 程序员决定是返回相同的源实体还是投影。
由于 (3),直接实现不会从投影类中找到字段,因为我有一个基/实体类型的静态类型。然后我开始更改代码以考虑结果类型。
我有一种感觉,这只是静态类型的阻碍,在这里并没有真正的帮助。不幸的是IQueryable<dynamic> 不起作用。
示例代码(为简洁起见省略详细信息):
void Main()
{
using (var db = new MyContext())
{
var original = db.Set<Sample>();
// requirement (3), static type Sample, dynamic type SampleDTO
Expression<Func<Sample, Sample>> fn = item => new SampleDTO() { Description = "Value: " + item.Name};
var projected = original.Select(fn);
// requirements (1) and (2)
var ordered = OrderBy_Default<Sample, SampleDTO>(projected, "Description");
ordered.Dump();
}
}
private IQueryable<T> OrderBy_Default<T, TProject>(IQueryable<T> source, string ordering)
{
var type = source.ElementType;
var resultType = type;
var property = resultType.GetProperty(ordering, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
var parameter = Expression.Parameter(resultType, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable),
"OrderBy",
new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExp));
return source.Provider.CreateQuery<T>(resultExp);
}
前面的代码产生了这个错误:
类型“Queryable”的通用方法“OrderBy”与提供的类型参数和参数不兼容。如果方法是非泛型的,则不应提供类型参数。
我试过projected.Cast<SampleDTO>():
无法将类型“Sample”转换为类型“UserQuery+SampleDTO”。 LINQ to Entities 仅支持转换 EDM 基元或枚举类型。
我试过projected.OfType<SampleDTO>():
'UserQuery+SampleDTO' 不是类型过滤操作的有效元数据类型。类型过滤仅对实体类型和复杂类型有效。
Cast() 和 OfType() 适用于 L2O,但不适用于 L2EF。
将SampleDTO 添加到实体模型当然不是答案(不过为了了解它的工作原理,已经尝试过了)。
我的实体和预测:
public class Sample
{
public int Id { get; set; }
public string Name { get; set; }
}
public class SampleDTO: Sample
{
public string Description { get; set; }
}
我让 SampleDTO 继承自 Sample,这很有帮助。这不是一个要求,这是一个方便的问题。
一些可能的答案:
我可以使用Expression<Func<Sample, SampleDTO>>,而不是Expression<Func<Sample, Sample>>。这会使要求 (3) 无效,并且会破坏我现有的大部分代码。
PS:我正在考虑使用 Microsoft Dynamic LINQ 库,但为了得到答案,我期待知道到底发生了什么。
【问题讨论】:
-
相同的结果:“ParseException:‘样本’类型中不存在属性或字段‘描述’”
标签: c# linq entity-framework dto