EF Core 动态包含和排序
EF Core dynamic include and order
我正在尝试包括相关实体并对其进行排序。
如果您知道实体和相关项目,它可以简单到:
context.Set<Item>().Include(x => x.SubItems.OrderBy(x => x.Name));
现在我正在尝试动态复制上述场景,结果应该是这样的:
{[Microsoft.EntityFrameworkCore.Query.QueryRootExpression].Include(x => x.SubItems.OrderBy(y => y.Name))}
但我得到的最接近的是:
{[Microsoft.EntityFrameworkCore.Query.QueryRootExpression].Include(x => x.SubItems).OrderBy(y => y.Name)}
我在这里做错了什么?这是我的代码:
private static IQueryable<T> IncludeNaviagations<T>(DbContext context, IQueryable<T> queryable)
{
var type = typeof(T);
foreach (var nav in context.Model.FindEntityType(typeof(T)).GetNavigations())
{
var method = IncludeMethodInfo.MakeGenericMethod(new[] { type, type.GetProperty(nav.Name).PropertyType });
var includeParam = Expression.Parameter(type, "x");
var includeProperty = Expression.Property(includeParam, nav.Name);
var includeLambda = Expression.Lambda(includeProperty, includeParam);
var include = Expression.Call(instance: null, method: IncludeMethodInfo.MakeGenericMethod(type, nav.PropertyInfo.PropertyType), arguments: new[] { queryable.Expression, Expression.Quote(includeLambda) });
var orderColumn = "Name";
var property = type.GetProperty(orderColumn);
var param = Expression.Parameter(type, "y");
var propName = Expression.Property(param, orderColumn);
var sort = Expression.Lambda(propName, param);
var result = Expression.Call(typeof(Queryable), "OrderBy", new[] { type, sort.ReturnType }, include, Expression.Quote(sort));
queryable = queryable.Provider.CreateQuery<T>(result);
}
return queryable;
}
PS。上面的方法将进行一些调整以递归地执行包含。
在这上面花了很多时间后,我开始工作了,这里是一个拼凑的解决方案:
OrderByMethodInfo = typeof(Enumerable).GetMethods().First(x => x.Name == "OrderBy" && x.GetParameters().Length == 2);
var orderColumnType = subType.GetProperty(orderColumn).PropertyType;
orderByMethod = orderByMethod.MakeGenericMethod(subType, orderColumnType);
var includeParam = Expression.Parameter(nav.ParentType, "x");
var includeProperty = Expression.Property(includeParam, nav.Name);
var property = nav.ParentType.GetProperty(orderColumn);
var param = Expression.Parameter(subType, "y");
var propName = Expression.Property(param, orderColumn);
var sort = Expression.Lambda(propName, param);
var order = Expression.Call(orderByMethod, includeProperty, sort);
var orderLambda = Expression.Lambda(order, Expression.Parameter(nav.ParentType, "x"));
var orderQuote = Expression.Quote(orderLambda);
var includeMethod = IncludeMethodInfo.MakeGenericMethod(nav.ParentType, typeof(IOrderedEnumerable<>).MakeGenericType(subType));
result = Expression.Call(instance: null, method: includeMethod, arguments: new[] { queryable.Expression, orderQuote });
queryable.Provider.CreateQuery<object>(result);
您可以使用Noobercong.DynamicInclude包
您的示例的表达式是
context.Set<Item>().DynamicInclude("SubItems<Name>");
我正在尝试包括相关实体并对其进行排序。
如果您知道实体和相关项目,它可以简单到:
context.Set<Item>().Include(x => x.SubItems.OrderBy(x => x.Name));
现在我正在尝试动态复制上述场景,结果应该是这样的:
{[Microsoft.EntityFrameworkCore.Query.QueryRootExpression].Include(x => x.SubItems.OrderBy(y => y.Name))}
但我得到的最接近的是:
{[Microsoft.EntityFrameworkCore.Query.QueryRootExpression].Include(x => x.SubItems).OrderBy(y => y.Name)}
我在这里做错了什么?这是我的代码:
private static IQueryable<T> IncludeNaviagations<T>(DbContext context, IQueryable<T> queryable)
{
var type = typeof(T);
foreach (var nav in context.Model.FindEntityType(typeof(T)).GetNavigations())
{
var method = IncludeMethodInfo.MakeGenericMethod(new[] { type, type.GetProperty(nav.Name).PropertyType });
var includeParam = Expression.Parameter(type, "x");
var includeProperty = Expression.Property(includeParam, nav.Name);
var includeLambda = Expression.Lambda(includeProperty, includeParam);
var include = Expression.Call(instance: null, method: IncludeMethodInfo.MakeGenericMethod(type, nav.PropertyInfo.PropertyType), arguments: new[] { queryable.Expression, Expression.Quote(includeLambda) });
var orderColumn = "Name";
var property = type.GetProperty(orderColumn);
var param = Expression.Parameter(type, "y");
var propName = Expression.Property(param, orderColumn);
var sort = Expression.Lambda(propName, param);
var result = Expression.Call(typeof(Queryable), "OrderBy", new[] { type, sort.ReturnType }, include, Expression.Quote(sort));
queryable = queryable.Provider.CreateQuery<T>(result);
}
return queryable;
}
PS。上面的方法将进行一些调整以递归地执行包含。
在这上面花了很多时间后,我开始工作了,这里是一个拼凑的解决方案:
OrderByMethodInfo = typeof(Enumerable).GetMethods().First(x => x.Name == "OrderBy" && x.GetParameters().Length == 2);
var orderColumnType = subType.GetProperty(orderColumn).PropertyType;
orderByMethod = orderByMethod.MakeGenericMethod(subType, orderColumnType);
var includeParam = Expression.Parameter(nav.ParentType, "x");
var includeProperty = Expression.Property(includeParam, nav.Name);
var property = nav.ParentType.GetProperty(orderColumn);
var param = Expression.Parameter(subType, "y");
var propName = Expression.Property(param, orderColumn);
var sort = Expression.Lambda(propName, param);
var order = Expression.Call(orderByMethod, includeProperty, sort);
var orderLambda = Expression.Lambda(order, Expression.Parameter(nav.ParentType, "x"));
var orderQuote = Expression.Quote(orderLambda);
var includeMethod = IncludeMethodInfo.MakeGenericMethod(nav.ParentType, typeof(IOrderedEnumerable<>).MakeGenericType(subType));
result = Expression.Call(instance: null, method: includeMethod, arguments: new[] { queryable.Expression, orderQuote });
queryable.Provider.CreateQuery<object>(result);
您可以使用Noobercong.DynamicInclude包
您的示例的表达式是
context.Set<Item>().DynamicInclude("SubItems<Name>");