使用反射的实体框架排序 [英] Entity framework ordering using reflection

查看:30
本文介绍了使用反射的实体框架排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用于排序的扩展方法,sortExpression 可以是Description"或Description DESC"之类的东西,它非常适合同一个表中的列:

I have an extension method for ordering, the sortExpression can be something like "Description" or "Description DESC", it is working perfectly for columns at the same table:

 public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortExpression)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        if (string.IsNullOrEmpty(sortExpression))
            return source;

        var parts = sortExpression.Split(' ');
        var isDescending = false;
        var propertyName = "";
        var type = typeof(T);

        if (parts.Length > 0 && parts[0] != "")
        {
            propertyName = parts[0];

            if (parts.Length > 1)
                isDescending = parts[1].ToLower().Contains("esc");

            var prop = type.GetProperty(propertyName);
            if (prop == null)
                throw new ArgumentException(string.Format("No property '{0}' on type '{1}'", propertyName, type.Name));

            var funcType = typeof(Func<,>)
                .MakeGenericType(type, prop.PropertyType);

            var lambdaBuilder = typeof(Expression)
                .GetMethods()
                .First(x => x.Name == "Lambda" && x.ContainsGenericParameters && x.GetParameters().Length == 2)
                .MakeGenericMethod(funcType);

            var parameter = Expression.Parameter(type);
            var propExpress = Expression.Property(parameter, prop);

            var sortLambda = lambdaBuilder
                .Invoke(null, new object[] { propExpress, new ParameterExpression[] { parameter } });

            var sorter = typeof(Queryable)
                .GetMethods()
                .FirstOrDefault(x => x.Name == (isDescending ? "OrderByDescending" : "OrderBy") && x.GetParameters().Length == 2)
                .MakeGenericMethod(new[] { type, prop.PropertyType });

            var result = (IQueryable<T>)sorter
                .Invoke(null, new object[] { source, sortLambda });
            return result;
        }

        return source;
    }

工作示例:

    var query = db.Audit.Include("AccessLevel").AsQueryable();
    query = query.OrderBy("Description");

请注意,描述"列存在于同一个审计"表中.

Please note that the "Description" column exists at the same table "Audit".

我想要做的是按关系表中的列排序:

What I'm trying to do is to sort by a column in a relation table:

喜欢下面的

  var query = db.Audit.Include("AccessLevel").AsQueryable();
  query = query.OrderBy("AccessLevel.Name");

相当于:

query = query.OrderBy(o => o.AccessLevel.Name);

我的扩展方法需要什么修改?

What is the required modification on my extension method ?

推荐答案

我用下面的代码解决了:

I solved it by using the following code:

 public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
        {

                return ApplyOrder<T>(source, parts[0], "OrderBy");

        }
        public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "OrderByDescending");
        }
        public static IQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "ThenBy");
        }
        public static IQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "ThenByDescending");
        }
        static IQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
        {

            if (source == null)
                throw new ArgumentNullException("source");

            if (string.IsNullOrEmpty(property))
                return source;


            string[] props = property.Split('.');
            Type type = typeof(T);
            ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg;
            foreach (string prop in props)
            {
                // use reflection (not ComponentModel) to mirror LINQ
                PropertyInfo pi = type.GetProperty(prop);
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

            object result = typeof(Queryable).GetMethods().Single(
                    method => method.Name == methodName
                            && method.IsGenericMethodDefinition
                            && method.GetGenericArguments().Length == 2
                            && method.GetParameters().Length == 2)
                    .MakeGenericMethod(typeof(T), type)
                    .Invoke(null, new object[] { source, lambda });
            return (IQueryable<T>)result;
        }

这篇关于使用反射的实体框架排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆