LINQ to Entities Does Not Recognize Method Method Method Name

I had a similar problem that was asked here: LINQ to Entities does not recognize the 'System.String ToString ()' method, and this method cannot be translated into a storage expression

I am trying to split pages into my source, but in my case I cannot put the result of GetPropertyValue into a variable because I need x to do this:

 public IEnumerable<TModel> Paginate(IQueryable<TModel> source, ref int totalPages, int pageIndex, int pageSize, string sortfield, SortDirection? sortdir) { totalPages = (int)Math.Ceiling(source.Count() / (double)pageSize); if (sortdir == SortDirection.Descending) { return source.OrderByDescending(x => GetPropertyValue(x, sortfield)).Skip(pageIndex * pageSize).Take(pageSize).ToList(); } else { return source.OrderBy(x => GetPropertyValue(x, sortfield)).Skip(pageIndex * pageSize).Take(pageSize).ToList(); } } private static object GetPropertyValue(object obj, string name) { return obj == null ? null : obj.GetType().GetProperty(name).GetValue(obj, null); } 

What could I do in this case?

+6
source share
2 answers

Lambda expressions (those used inside Where, OrderBy, etc.) cannot contain any C # code, they can only contain an expression tree that is translated into SQL. You cannot invoke any arbitrary methods there other than those mentioned in the EF documentation, such as SqlFunctions, etc.

To do a sort with a field name at runtime, you need to create a lambda expression at runtime and pass it.

 public IEnumerable<TModel> Paginate(IQueryable<TModel> source, ref int totalPages, int pageIndex, int pageSize, string sortfield, SortDirection? sortdir) { totalPages = (int)Math.Ceiling(source.Count() / (double)pageSize); if (sortdir == SortDirection.Descending) { return source.OrderByDescending(sortfield).Skip(pageIndex * pageSize).Take(pageSize).ToList(); } else { return source.OrderBy(sortfield).Skip(pageIndex * pageSize).Take(pageSize).ToList(); } } public static class QueryableHelper { public static IQueryable<TModel> OrderBy<TModel>(this IQueryable<TModel> q, string name) { Type entityType = typeof(TModel); PropertyInfo p = entityType.GetProperty(name); MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByProperty").MakeGenericMethod(entityType, p.PropertyType); return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p }); } public static IQueryable<TModel> OrderByDescending<TModel>(this IQueryable<TModel> q, string name) { Type entityType = typeof(TModel); PropertyInfo p = entityType.GetProperty(name); MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByPropertyDescending").MakeGenericMethod(entityType, p.PropertyType); return (IQueryable<TModel>)m.Invoke(null, new object[] { q, p }); } public static IQueryable<TModel> OrderByPropertyDescending<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p) { ParameterExpression pe = Expression.Parameter(typeof(TModel)); Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object)); return q.OrderByDescending(Expression.Lambda<Func<TModel, TRet>>(se, pe)); } public static IQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p) { ParameterExpression pe = Expression.Parameter(typeof(TModel)); Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object)); return q.OrderBy(Expression.Lambda<Func<TModel, TRet>>(se, pe)); } } 

This solution only works at the level of one level, but if you need nested levels than you need more work, you can probably see the next SDK that does all this.

However, if you look at the Entity REST SDK itself, it has a lot of things and everything you might need. Disclaimer: I am the author.

https://entityrestsdk.codeplex.com

+6
source

Instead of using reflection, you should dynamically create an Expression<Func<TSource, TOrder>> and pass it to OrderBy .

Take a look here to understand how to create a dynamic query.

+1
source

Source: https://habr.com/ru/post/950745/