2013-04-15 12 views
6

Sto usando modelli qui menzionati http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-applicationdinamica Func <IQueryable <TEntity>, IOrderedQueryable <TEntity>> Espressione

e sto usando il metodo seguito per interrogare EF

public virtual IEnumerable<TEntity> Get(
     Expression<Func<TEntity, bool>> filter = null, 
     Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
     string includeProperties = "") 
    { 
     IQueryable<TEntity> query = dbSet; 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     foreach (var includeProperty in includeProperties.Split 
      (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      query = query.Include(includeProperty); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 
    } 

Ora voglio creare dinamiche Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> espressione ordina i miei dati.

Io so solo il nome del campo come stringa e l'ordine di tipo (ascendente, discendente) come stringa (asc, decrescente)

+0

Questa non è la forma usuale di un ordine-by; hai visto questo? http://stackoverflow.com/questions/41244/dynamic-linq-orderby –

+0

@MarcGravell grazie, l'ho visto. Ma il tutorial di MS contiene questo codice, quindi sto cercando di scrivere un LINQ dinamico adatto per questo. In realtà penso di aver avuto successo, ma devo fare alcuni test e poi farti sapere. –

risposta

9

finalmente potrei scrivere il metodo che voglio.

public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetOrderBy(string orderColumn, string orderType) { 
      Type typeQueryable = typeof(IQueryable<TEntity>); 
      ParameterExpression argQueryable = Expression.Parameter(typeQueryable, "p"); 
      var outerExpression = Expression.Lambda(argQueryable, argQueryable); 
      string[] props = orderColumn.Split('.'); 
      IQueryable<TEntity> query = new List<TEntity>().AsQueryable<TEntity>(); 
      Type type = typeof(TEntity); 
      ParameterExpression arg = Expression.Parameter(type, "x"); 

      Expression expr = arg; 
      foreach(string prop in props) { 
       PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 
       expr = Expression.Property(expr, pi); 
       type = pi.PropertyType; 
      } 
      LambdaExpression lambda = Expression.Lambda(expr, arg); 
      string methodName = orderType == "asc" ? "OrderBy" : "OrderByDescending"; 

      MethodCallExpression resultExp = 
       Expression.Call(typeof(Queryable), methodName, new Type[] { typeof(TEntity), type }, outerExpression.Body, Expression.Quote(lambda)); 
      var finalLambda = Expression.Lambda(resultExp, argQueryable); 
      return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)finalLambda.Compile(); 
     } 

Questo metodo richiede due parametri, prima un nome di campo altro è asc o desc. Il risultato del metodo può essere utilizzato direttamente con l'oggetto IQueryable.

Grazie per la vostra aiuta

2

Non sono sicuro di cosa esattamente si vuole realizzare, ma aveva cambiato il codice e aggiungere un po ' esempio per dimostrare come funziona.

Questa è una semplice app per console, che ha dummyText come lista. Il metodo interrogabile consente di utilizzare il filtro e l'espressione di ordinamento come desideri. Spero che lo aiuti

class Program 
{ 

    private List<string> _dummyText = new List<string>(){ "Arda", 
     "Araba", 
     "Antartika", 
     "Balon"}; 

    static void Main(string[] args) 
    { 
     Program p = new Program(); 
     List<string> result = p.Get(s => s.StartsWith("A"), orderBy: q => q.OrderBy(d => d.Length)).ToList(); 

     Console.ReadLine(); 
    } 


    public virtual IEnumerable<string> Get(
    Expression<Func<string, bool>> filter = null, 
    Func<IQueryable<string>, IOrderedQueryable<string>> orderBy = null) 
    { 

     IQueryable<string> query = _dummyText.AsQueryable(); 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 



    } 

} 
+0

grazie per la risposta, ma penso che ci sia qualche incompreso. Devo inviare z => z.OrderBy (x => x.CreatedDate) al parametro orderBy. Quindi la tua risposta non funzionerà secondo me. –

+0

È possibile utilizzare alcuni parametri esterni nell'espressione linq per eseguire l'esecuzione del metodo condizionale come inline se ... Es: string direct = "DESC"; Lista result = p.Get (s => s.StartsWith ("A"), orderBy: q => ((direct == "ASC")? Q.OrderBy (d => d.Length): q. OrderByDescending (d => d.Length))). ToList(); Ma suppongo che questo non sia esattamente quello che vuoi ... – Arda

1

Questo è molto in ritardo alla festa, ma la risposta corretta si trova su un altro interrogativo https://stackoverflow.com/a/10935223/14275

var students = repository.Get(x => x.FirstName = "Bob",q => q.OrderBy(s => s.LastName)); 
Problemi correlati