LINQ dynamic expression to sort a navigation property

MVC3, Entity Framework 4.1 Code First.

Work with 2 tables

Model:

public class UniversityMaster { [Key] public string UniversityId { get; set; } public string UniversityName { get; set; } } public class ProgramMaster { [Key] public string ProgramId { get; set; } public string ProgramName { get; set; } public string UniversityId { get; set; } public virtual UniversityMaster University { get; set; } // navigation property } 

Dynamic expression for sorting (just to avoid the case switch statement):

 public virtual IQueryable< ProgramMaster > GetQueryableSort(string sortField="", string sortDirection="") { IQueryable<ProgramMaster> query = _dbSet; ParameterExpression pe = Expression.Parameter(typeof(ProgramMaster), string.Empty); MemberExpression property = Expression.PropertyOrField(pe, sortField); //get a exception here if the sort field is of navigation property (University.UniversityName) LambdaExpression lambda = Expression.Lambda(property, pe); if (sortDirection == "ASC") orderbydir = "OrderBy"; else orderbydir = "OrderByDescending"; MethodCallExpression call = Expression.Call(typeof(Queryable), orderbydir, new Type[] { typeof(TEntity), property.Type }, query.Expression, Expression.Quote(lambda)); var returnquery = (IOrderedQueryable<ProgramMaster>)query.Provider.CreateQuery< ProgramMaster >(call); return returnquery; } 

The page displays a grid with two columns. Program name and university name using webgrid. The sorting function for the "Program Name" column, however, failed if it was sorted by university name, because this property is in UniversityMaster, and Expression.PropertyOrField searches for this property in ProgramMaster. Here is the exception:

University.UniversityName 'is not a member of the type' App.Core.Model.ProgramMaster

My question is how I do this work for the navigation properties of my model class.

I hope I could explain the scenario. Any help is appreciated.

+6
source share
2 answers

Microsoft has a DynamicQueryable class that can be used to dynamically build specific parts of a LINQ query using strings. With this, you can say myQuery.OrderBy ("University.UniversityName"), and it will handle the construction of the expression. The same library also supports the dynamic construction of SELECT and WHERE clauses.

You can find a copy of the source as part of the excellent Loresoft EntityFramework.Extended package. The Microsoft file is located at https://github.com/loresoft/EntityFramework.Extended/blob/master/Source/EntityFramework.Extended/Dynamic/DynamicQueryable.cs

+1
source

Good, because MemberExpression trying to call a member with the Univerty.UniversityName parameter. What you want to do is call a member named Univerity in the parameter, and then call UniversityName . In fact, you need to iteratively resolve property names.

 public virtual IQueryable< ProgramMaster > GetQueryableSort(string sortField = "", string sortDirection = "") { IQueryable<ProgramMaster> query = _dbSet; var propertyNames = sortField.Split("."); ParameterExpression pe = Expression.Parameter(typeof(ProgramMaster), string.Empty); Expression property = pe; foreach(var prop in propertyName) { property = Expression.PropertyOrField(property, prop); } LambdaExpression lambda = Expression.Lambda(property, pe); if (sortDirection == "ASC") orderbydir = "OrderBy"; else orderbydir = "OrderByDescending"; MethodCallExpression call = Expression.Call( typeof(Queryable), orderbydir, new Type[] { typeof(TEntity), property.Type }, query.Expression, Expression.Quote(lambda)); var returnquery = (IOrderedQueryable<ProgramMaster>)query.Provider.CreateQuery<ProgramMaster>(call); return returnquery; } 
0
source

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


All Articles