2010-12-28 5 views
3

Ich bin triying, um eine Funktion zu machen, die eine where-Klausel zu einer Abfrage hinzufügt, die auf einer Eigenschaft und einem Wert basiert. Dies ist eine sehr einfache Version meiner Funktion.Hilfe mit Linq und Generics. GetValue innerhalb einer Abfrage verwenden

Private Function simplified(ByVal query As IQueryable(Of T), ByVal PValue As Long, ByVal p As PropertyInfo) As ObjectQuery(Of T) 

    query = query.Where(Function(c) DirectCast(p.GetValue(c, Nothing), Long) = PValue) 
    Dim t = query.ToList 'this line is only for testing, and here is the error raise 
    Return query 

End Function 

Die Fehlermeldung lautet: LINQ to Entities nicht die Methode in einen Laden Ausdruck 'System.Object CompareObjectEqual (System.Object, System.Object, Boolean)' Methode, und diese Methode kann nicht erkennt übersetzt.

Sieht so aus, als könnte ein GetValue in einer linq-Abfrage nicht verwendet werden. Kann ich das auf andere Weise erreichen?

Veröffentlichen Sie Ihre Antwort in C#/VB. Wählen Sie einen, bei dem Sie sich wohler fühlen.

Dank

EDIT: Statt ich auch diesen Code mit dem gleichen Ergebnis versucht

Private Function simplified2(ByVal query As IQueryable(Of T)) 

    query = From q In query 
      Where q.GetType.GetProperty("Id").GetValue(q, Nothing).Equals(1) 
      Select q 
    Dim t = query.ToList 
    Return query 
End Function 

Antwort

6

Sie müssen den Code in einen Ausdrucksbaum konvertieren.

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace WindowsFormsApplication1 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      using (var context = new NorthwindEntities()) 
      { 
       IQueryable<Customer> query = context.Customers; 
       query = Simplified<Customer>(query, "CustomerID", "ALFKI"); 
       var list = query.ToList(); 
      } 
     } 

     static IQueryable<T> Simplified<T>(IQueryable<T> query, string propertyName, string propertyValue) 
     { 
      PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName); 
      return Simplified<T>(query, propertyInfo, propertyValue); 
     } 

     static IQueryable<T> Simplified<T>(IQueryable<T> query, PropertyInfo propertyInfo, string propertyValue) 
     { 
      ParameterExpression e = Expression.Parameter(typeof(T), "e"); 
      MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo); 
      ConstantExpression c = Expression.Constant(propertyValue, propertyValue.GetType()); 
      BinaryExpression b = Expression.Equal(m, c); 

      Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(b, e); 
      return query.Where(lambda); 
     } 
    } 
} 
+0

Getestet und funktioniert. Perfekt. Vielen Dank. – Jonathan

+0

Hallo Tom. Könnten Sie mir den Link zur Verfügung stellen oder die kurze Beschreibung erhalten, warum er mit Ausdrucksbäumen funktioniert, aber nicht direkt mit Lambda arbeitet? – Ph0en1x

0

Haben Sie die DirectCast versucht herausziehen und die Reflexion über den Lambda-Parameter? Etwas wie folgt aus:

query.Where(Function(c) _ 
    c.GetType().GetProperty(p, GetType("Int64")).GetValue(c, Nothing) = PValue) 

Ich bin nicht sicher, dass Sie auch diese Art der Sache in einem Lambda tun können, aber es ist einen Versuch wert.

+0

Ich habe versucht, diese mit dem gleichen Fehler: query = query.Where (.. Funktion (c) c.GetType() GetProperty ("ID") GetValue (c, Nothing) .Equals (PValue)) '' 'Ich habe hier einen Eigenschaftsnamen verwendet, von dem ich weiß, dass er existiert, um zu vereinfachen – Jonathan