【问题标题】:Dynamic LINQ Expression for sorting navigation property用于排序导航属性的动态 LINQ 表达式
【发布时间】:2025-11-21 06:50:14
【问题描述】:

MVC3,Entity Framework 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 的网格。 Program Name 列的排序工作正常,但是如果按 University Name 排序则失败,因为此属性位于 UniversityMaster 中,Expression.PropertyOrField 在 ProgramMaster 中搜索此属性。这是一个例外:

University.UniversityName' 不是“App.Core.Model.ProgramMaster”类型的成员

我的问题是我如何使这项工作适用于我的模型类的导航属性。

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

【问题讨论】:

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


    【解决方案1】:

    那是因为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;
    }
    

    【讨论】:

    • 优秀。按预期工作。
    【解决方案2】:

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

    您可以在 Loresoft 出色的 EntityFramework.Extended 包中找到源代码的副本。微软的文件在https://github.com/loresoft/EntityFramework.Extended/blob/master/Source/EntityFramework.Extended/Dynamic/DynamicQueryable.cs

    【讨论】:

      最近更新 更多