2013-04-15 11 views
6

I Muster verwenden hier erwähnt 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-applicationDynamische Func <IQueryable <TEntity>, IOrderedQueryable <TEntity>> Expression

Und ich unten bin mit Methode EF abzufragen

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

Jetzt mag ich dynamischen Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> Ausdruck erstellen Bestell meine Daten.

Ich weiß nur, Feldnamen als String und Auftragsart (aufsteigend, absteigend) als String (auf, ab)

+0

auf eine andere Frage befindet, die nicht die übliche Form für auftrags durch ist; hast du das gesehen? http://Stackoverflow.com/questions/41244/dynamic-linq-orderby –

+0

@MarcGravell danke, ich sah das. Aber das Tutorial von MS enthält diesen Code, also versuche ich, dafür geeignete dynamische LINQ zu schreiben. Eigentlich glaube ich, dass ich erfolgreich war, aber ich muss einige Tests machen und Sie dann informieren. –

Antwort

9

endlich könnte ich die Methode schreiben, die ich will.

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

Diese Methode hat zwei Parameter, einen ersten Feldnamen andere ist, aufsteigend oder absteigend. Ergebnis der Methode kann direkt mit IQueryable Objekt verwendet werden.

Vielen Dank für Ihre hilft

2

Ich bin nicht sicher, was genau Sie erreichen wollen, aber ich habe den Code geändert und fügen Sie einige Beispiel, um zu demonstrieren, wie es funktioniert.

Dies ist eine einfache Konsole App, die DummyText als Liste hat. Die abfragbare Methode ermöglicht das Filtern und Sortieren von Ausdrücken nach Ihren Wünschen. Ich hoffe es hilft

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

danke für die Antwort, aber ich denke, es gibt einige missverstanden. Ich muss z => z.OrderBy (x => x.CreatedDate) an orderBy Parameter senden. Deine Antwort wird meiner Meinung nach nicht funktionieren. –

+0

Sie können einige externe Parameter zu linq Ausdruck verwenden, um bedingte Methodenausführung als inline zu haben, wenn ... Beispiel: string direct = "DESC"; Liste Ergebnis = p.Get (s => s.StartsWith ("A"), orderBy: q => ((direkt == "ASC")? Q.OrderBy (d => d.Length): q. OrderByDescending (d => d.Length))). ToList(); Aber ich frage das ist nicht genau das, was Sie wollen ... – Arda