2012-02-24 28 views
6

MVC3, Entity Framework 4.1 Primero el código.Dynamic LINQ Expression para clasificar la propiedad de navegación

Trabajar con 2 mesas

Modelo:

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 

} 

expresión dinámica para la clasificación (sólo para evitar una declaración de caso interruptor):

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

La página está mostrando una cuadrícula con dos columnas Nombre del programa y nombre de la universidad usando webgrid. La clasificación funciona bien para la columna Nombre del programa; sin embargo, falla si se ordena por nombre de universidad, ya que esta propiedad se encuentra en UniversityMaster y Expression.PropertyOrField busca esta propiedad en ProgramMaster. Aquí es la excepción:

University.UniversityName 'no es un miembro de tipo' App.Core.Model.ProgramMaster

Mi pregunta es cómo hacer este trabajo para las propiedades de navegación de mi clase del modelo .

Espero haber podido explicar el escenario. Cualquier ayuda es apreciada.

Respuesta

0

Bueno, eso es porque el MemberExpression está tratando de llamar a un miembro llamado Univerty.UniversityName en el parámetro. Lo que quiere hacer es llamar a un miembro llamado Univerity en el parámetro, luego llame al UniversityName en eso. De hecho, necesita iterativamente resolver los nombres de las propiedades.

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

Microsoft tiene una clase DynamicQueryable que se puede usar para construir dinámicamente ciertas partes de una consulta LINQ utilizando strings. Con esto puedes decir myQuery.OrderBy ("University.UniversityName") y se encargará de compilar la expresión. La misma biblioteca también admite la construcción dinámica de las cláusulas SELECT y WHERE.

Puede encontrar una copia de la fuente como parte del excelente paquete EntityFramework.Extended de Loresoft. El archivo de Microsoft está en https://github.com/loresoft/EntityFramework.Extended/blob/master/Source/EntityFramework.Extended/Dynamic/DynamicQueryable.cs

Cuestiones relacionadas