【发布时间】:2019-03-22 07:46:54
【问题描述】:
我有自定义 OrderBy 实现,它只适用于没有继承的类型,如果我想从我得到的基类型中按字段排序 无法翻译 LINQ 表达式
public static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (string.IsNullOrEmpty(orderByProperty))
{
throw new ArgumentNullException(nameof(orderByProperty));
}
var command = desc ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);
var param = Expression.Parameter(type, "p");
var property = type.GetProperty(orderByProperty);
var propertyAccess = Expression.MakeMemberAccess(param, property);
var orderByExpression = Expression.Lambda(propertyAccess, param);
var resultExpression = Expression.Call(
typeof(Queryable),
command,
new Type[] { type, property.PropertyType },
source.Expression,
Expression.Quote(orderByExpression));
return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery(resultExpression);
}
我正在使用 entityframework core 2.2,但非常有趣的是,如果我只写 source.OrderBy(x=>x.someBaseField),那么它可以毫无问题地工作,所以我的自定义实现必须有一些东西
在错误日志中,我还得到了翻译后的查询,看起来像这样,有趣的是结尾部分
orderby new SomeType() {NewField = [entity].DbField, Id = [entity].Id}.Id desc
orderByExpression.Body {p => p.Id}
resultExpression
.Call System.Linq.Queryable.OrderByDescending(
.Call System.Linq.Queryable.Select(
.Call System.Linq.Queryable.Where(
.Call System.Linq.Queryable.Where(
.Constant<Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MyTypeView]>(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MyTypeView]),
'(.Lambda #Lambda1<System.Func`2[MyTypeView,System.Boolean]>)),
'(.Lambda #Lambda2<System.Func`2[MyTypeView,System.Boolean]>)),
'(.Lambda #Lambda3<System.Func`2[MyTypeView, MyTypeResult]>))
,
'(.Lambda #Lambda4<System.Func`2[MyTypeResult,System.Guid]>))
【问题讨论】:
-
我会先尝试一个稍微简单一点的版本,没有“按点分割” - 你有那很多工作吗?
-
@JonSkeet 嗨,乔恩,我只是简单地说,但问题是一样的。
-
好的,很好 - 这简化了事情。如果您打印出
orderByExpression和resultExpression,它们看起来像您期望的那样吗? -
@JonSkeet 对我来说看起来不错,我更新了问题,没有包含所有 lambdas 定义,仅模板
-
嗯……我也觉得不错。出于兴趣,如果您通过
AsQueryable使用List<T>作为源,代码是否有效?如果没有,minimal reproducible example 表明这将非常有用。
标签: c# .net-core entity-framework-core