Erstellen Sie IQueryable.Any mit Ausdrucksbaumstrukturen für LINQ-Abfragen

c# expression-trees

Frage

Ich baue eine SQL "WHERE" -Klausel dynamisch unter Verwendung der System.Linq.Expressions.Expression-Klasse. Es funktioniert gut für einfache Klauseln, zB um "PhaseCode = X" -Klausel hinzuzufügen, mache ich folgendes:

var equalTarget = Expression.Constant(phaseCode, typeof(int?));
var phaseEquals = Expression.Equal(Expression.PropertyOrField(projParam, "PhaseCode"), equalTarget);

Jetzt versuche ich jedoch, einen Ausdruck zu erstellen, der den Datensatz zurückgibt, wenn ein Projekt einer bestimmten Gruppe zugewiesen wurde. Projekt und Gruppe haben eine Viele-zu-Viele-Beziehung. Ohne die Ausdrucksbäume würde ich es so machen:

db.Projects.Where(p => .... && p.GroupsAssigned.Any(g => g.ID == groupId))

Ich finde jedoch keine Möglichkeit, dies mit der Expression-Klasse auszudrücken. Es gibt zwei Dinge, die ich nicht herausfinden kann:

  • Wie durchqueren Sie die Beziehungen zwischen Tabellen
  • Wie macht man x.Any ()

Jede Hilfe wird sehr geschätzt.

Akzeptierte Antwort

Das Aufrufen einer Erweiterungsmethode wie Enumerable.Any oder Queryable.Any ist einfach ein Aufruf einer statischen Methode für die Sequenz und den Lambda-Ausdruck, den Sie für die WHERE Klausel erstellt haben. Sie können dazu Expression.Call verwenden:

// for Enumerable.Any<T>(IEnumerable<T>,Predicate<T>)
var overload = typeof(Enumerable).GetMethods("Any")
                                 .Single(mi => mi.GetParameters().Count() == 2);
var call = Expression.Call(
    overload,
    Expression.PropertyOrField(projParam, "GroupsAssigned"),
    anyLambda);      

Für Queryable.Any<T> müssen Sie dies in eine Methode rollen:

static Expression BuildAny<TSource>(Expression<Func<TSource, bool>> predicate)
{
    var overload = typeof(Queryable).GetMethods("Any")
                              .Single(mi => mi.GetParameters().Count() == 2);
    var call = Expression.Call(
        overload,
        Expression.PropertyOrField(projParam, "GroupsAssigned"),
        predicate);   

    return call;
}

Obwohl dies seltsam erscheint, können Sie dies nicht über eine normale Abfrage durchführen.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum