繁体   English   中英

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 package

您的示例的表达式是

context.Set<Item>().DynamicInclude("SubItems<Name>");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM