Wie übergibt man in LINQ to SQL Teile einer LINQ-Abfrage an eine Funktion?

c# expression-trees linq linq-to-sql

Frage

Ist es möglich, Teile einer linq Query in eine Funktion zu übergeben? Ich möchte eine gemeinsame Schnittstelle für meine DAL erstellen, die immer die gleiche Query-Schnittstelle verwendet. Beispielsweise,

List<T> Get(Join j, Where w, Select s){    
    return currentDataContext<T>.Join(j).Where(w).Select(s).ToList();    
}

Ist so etwas möglich? Ich denke, es würde mit Ausdrucksbäumen gemacht werden, aber ich konnte keine Beispiele dafür finden.

Akzeptierte Antwort

Nun, das "Join" ist knifflig, weil es sehr schwer ist, einen Join auszudrücken - aber Dinge wie wo / select / orderby sind ziemlich einfach ...

Wirklich, es ist nur ein Fall der Kombination der verschiedenen LINQ-Methoden auf IQueryable<T> , die in der Regel Expression<Func<...>> für einige Kombination akzeptieren. Eine grundlegende Auswahl mit einem optionalen Prädikat wäre also:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Ich würde auch gerne IQueryable<T> , da das vollständig zusammensetzbar ist. Wenn der Aufrufer eine Liste haben möchte, kann er immer ToList() darauf verwenden ... oder (zum Beispiel):

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

welches (mit Northwind) die Abfrage durchführt:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Das Problem mit der "Auswahl" (Projektion) in der Abfrage besteht darin, dass Sie mehrere generische Typen erhalten würden. Da die Projektion oft ein anonymer Typ sein soll, wäre es dann ziemlich unmöglich, den Projektionstyp (anonym) und den Tabellentyp anzugeben, und er wäre nicht aufrufbar.

In Wirklichkeit frage ich mich, ob es überhaupt von Vorteil ist, eine solche Methode zu schreiben. Ich könnte einfach bei einer Basismethode bleiben:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Und lassen Sie den Anrufer es in seiner bevorzugten Weise zusammensetzen - vielleicht mit der Abfragesyntax:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Welche verwendet:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Alternativ, wenn Sie wirklich die Reihenfolge und Projektion einbeziehen möchten, dann ist eine Erweiterungsmethode der praktikabelste Ansatz; dann müssen Sie nicht das Original (Quelle) T angeben (was es unmündlich macht, wenn es mit anon-Typen gemischt wird):

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Betrachten Sie dann eine DAL-Methode wie:

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Was verwendet (wieder mit Northwind):

    public IQueryable<T> Get<T>(
        Expression<Func<T,bool>> predicate
        ) where T : class
    {
        IQueryable<T> query = (IQueryable<T>)GetTable(typeof(T));
        if (predicate != null) query = query.Where(predicate);
        return query;
    }

Beliebte Antwort

Überprüfen Sie diese generische Klasse: TableView.cs .

Es verwendet im Grunde einen Delegierten Func <TEntity, bool>, um das Wo-Prädikat anzuwenden:

//...
public TableView(DataContext dataContext, Expression<Func<TEntity, bool>> predicate)
{
    this.table = dataContext.GetTable<TEntity>();
    this.baseQuery = table.Where(predicate);
    this.predicate = predicate.Compile();
}
//...



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