用于排序导航属性的动态LINQ表达式

时间:2012-02-24 13:34:17

标签: linq asp.net-mvc-3 entity

MVC3,实体框架4.1代码优先。

使用2个表

型号:

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

}

用于排序的动态表达式(仅用于避免switch case语句):

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;
    }

该页面使用webgrid显示一个包含两列Program Name和University Name的网格。 “程序名称”列的排序工作正常,但如果按大学名称排序则会失败,因为此属性位于UniversityMaster中,而Expression.PropertyOrField会在ProgramMaster中搜索此属性。这是一个例外:

  

University.UniversityName'不是'App.Core.Model.ProgramMaster

类型的成员

我的问题是如何使我的模型类的导航属性工作。

希望我能够解释这个场景。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

Microsoft有一个DynamicQueryable类,可用于使用字符串动态构造LINQ查询的某些部分。有了这个你可以说myQuery.OrderBy(&#34; University.UniversityName&#34;)它将处理构建表达式。同一个库还支持SELECT和WHERE子句的动态构造。

您可以找到源代码的副本,作为Loresoft优秀的EntityFramework.Extended包的一部分。 Microsoft的文件位于https://github.com/loresoft/EntityFramework.Extended/blob/master/Source/EntityFramework.Extended/Dynamic/DynamicQueryable.cs

答案 1 :(得分:0)

那是因为MemberExpression试图在参数上调用名为Univerty.UniversityName的成员。您要做的是在参数上调用名为Univerity的成员,然后在其上调用UniversityName。实际上,您需要迭代解析属性名称。

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;
}