2016-06-01 2 views
0

Ich möchte linq-Methode auf iqueryable mit einem Ausdrucksbaum von Funktion ausführen, wo ich Name der linq Methode und Name der Eigenschaft überließe. Aber meine Beispielmethode funktioniert nur mit zugeordneten Eigenschaften. Es wird eine Ausnahme ausgelöst, wenn ich beispielsweise versuche, die maximal berechnete Eigenschaft zu finden.Entity Framework führt eine Abfrage mit nicht zugeordneten Eigenschaften aus. Ausdrucksbaum

Meine Klassen:

public partial class Something 
    { 
     public int a { get; set; } 
     public int b { get; set; } 
    } 

    public partial class Something 
    { 
     public int calculated { get { return a * b; } } 
    } 

Probenmethode:

public static object ExecuteLinqMethod(IQueryable<T> q, string Field, string Method) 
    { 
     var param = Expression.Parameter(typeof(T), "p"); 

     Expression prop = Expression.Property(param, Field); 

     var exp = Expression.Lambda(prop, param); 

      Type[] types = new Type[] { q.ElementType, exp.Body.Type }; 
      var mce = Expression.Call(typeof(Queryable),Method,types,q.Expression,exp); 

      return q.Provider.Execute(mce); 
    } 
+1

Warum glauben Sie, dass der Ausdrucksbaum Ihnen erlauben kann, etwas zu tun, das nicht vom EF-Abfrageanbieter unterstützt wird? –

+0

Ich brauche eine universelle Methode, um Max, Min, Summe usw. von gemappten und nicht gemappten Eigenschaften zu finden. Mit dem angegebenen Namen der Funktion und dem Namen der Eigenschaft als Parameter dieser Methode. Es kann durch einen Ausdrucksbaum oder auf andere Weise erfolgen. –

+0

Warum finden Sie dann nicht zuerst den "anderen Weg" und fragen Sie dann, falls nötig, nach Hilfe für den Ausdrucksbaum. Ich denke, das Hauptproblem besteht darin, festzustellen, ob das Feld zugeordnet ist oder nicht. Und selbst wenn Sie das tun, da es keine Möglichkeit gibt zu wissen, was die berechnete Eigenschaft verwendet, ist die einzige Möglichkeit, sie auszuführen, die Ausführung gegen 'IEnumerable '. –

Antwort

0

zu können berechnet Eigenschaften abzufragen, müssen Sie mindestens 2 Möglichkeiten:

1) speichern Sie die berechnete Werte in der db mit den Zeilen (oder in einer anderen Tabelle), und verwenden Sie sie in Ihren Abfragen natürlich erfordert Datamodel Änderung und Redundanz in Daten, aber ist die performanteste Art und Weise. Aber ist das nicht aufregend, so gehen wir weiter zu

2) Sie müssen in der Lage sein, die Art auszudrücken, wie Sie die Eigenschaften auf eine Weise "berechnen", die sql verstehen wird, was bedeutet, dass die Eigenschaft durch eine linq ersetzt werden muss Ausdruck in der letzten Abfrage. Ich fand 2009 einen tollen Artikel von Eric Lippert über das Registrieren solcher Eigenschaften, aber ich finde es nicht mehr. Als solcher ist hier ein link zu einem anderen, der die gleiche Idee hat. Grundsätzlich definieren Sie Ihre Berechnung als Ausdrucksbaum und verwenden die kompilierte Version in Ihrem Code.

Um es bequemer zu machen, können Sie Ihre Immobilie mit einem

[AttributeUsage(AttributeTargets.Property)] 
class CalculatedByAttribute: Attribute 
{ 
    public string StaticMethodName {get; private set;} 
    public CalculatedByAttribute(string staticMethodName) 
    { 
     StaticMethodName = staticMethodName; 
    } 
} 

Wie Attribut würde:

public partial class Something 
{ 
    [CalculatedBy("calculatedExpression")] 
    public int calculated { get { return calculatedExpression.Compile()(this); } } 
    public static Expression<Func<Something, int>> calculatedExpression = s => s.a * s.b; 
} 

(natürlich können Sie die Kompilierung-Cache) :)

dann in Wenn die Eigenschaft Ihr Attribut hat, erhalten Sie den Wert der statischen Eigenschaft und verwenden dies in Ihren Abfragen. Etwas zusammen:

+0

Danke! Es funktioniert für die Berechnung von gemappten Eigenschaften, aber ich weiß nicht, was ich mit Berechnung basierend auf zugeordneten und berechneten Feldern tun soll. Wenn ich versuche, verschachtelten Ausdruck zu verwenden, erhalte ich den Fehler 'Der LINQ-Ausdrucksknotentyp' Invoke 'wird in LINQ to Entities nicht unterstützt.'.Zum Beispiel habe ich etwas wie folgt versucht: [CalculatedBy ("berechneteAusdruck1")] public int berechnete1 {get {return berechneteAusdruck1.Compile() (this); }} public static Ausdruck > comprectedExpression1 = s => sa.a * comprectedExpression.Compile() (s); –

+0

Bist du sicher, dass ich das war? 2009 war lange her, aber ich kann mich nicht erinnern, einen solchen Artikel geschrieben zu haben. Mein Microsoft-Kollege Matt Warren schrieb damals einige Artikel über diese Art von Dingen; Vielleicht denkst du an einen von ihnen? –

+0

@AdamBubula: Wenn Sie komplexere Szenarien erstellen müssen, überprüfen Sie diese Antwort: http://stackoverflow.com/questions/29448432/pass-expression-parameter-as-argument-to-another-expression/29471092#29471092 – MBoros

Verwandte Themen