Mit IEnumerable<T> und IQueryable<T> in ein generisches repository

Ich habe gelesen, der Anzahl der Beiträge, die in Bezug auf die Implementierung eines generischen repository. Ich habe auch gelesen eine Reihe von Beiträgen, die erklären, den Unterschied zwischen freilegen IEnumerable vs. IQueryable aus meinem repository.

Möchte ich die Flexibilität, dass meine Daten gefiltert, die in der Datenbank (anstatt in den Speicher durch den client), wollen aber vermeiden, dass die Definition eines eigenen repository-Schnittstelle für alle meine Einheiten (und konkreten Klassen, die diese Schnittstellen implementieren).

Soweit mein repository sieht wie folgt aus:

public interface IRepository<T>
{
    IEnumerable<T> GetAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> where);

    void Add(T entity);
    void Attach(T entity);
    void Delete(T entity);
}

und ein Beispiel für eine konkrete Umsetzung:

public class Repository<T> : IRepository<T> where T : class
{
    private DbContext _context;
    private DbSet<T> _entitySet;

    public Repository(DbContext context)
    {
        _context = context;
        _entitySet = _context.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return _entitySet;
    }

    public IEnumerable<T> Find(Expression<Func<T, bool>> where)
    {
        return _entitySet.Where(where);
    }

    public void Add(T entity)
    {
        _entitySet.Add(entity);
    }

    public void Attach(T entity)
    {
        _entitySet.Attach(entity);
    }

    public void Delete(T entity)
    {
        _entitySet.Remove(entity);
    }
}

In diesem Fall mein repository verwendet DbContext also was ich gerne wissen würde ist, wie das funktioniert mit dem generischen interface:

  1. IQueryable<T> stammt aus IEnumerable<T>. In Meiner Methode find bin ich wieder eines IQueryable<T> - Objekt, aber der client sieht nur diese als IEnumerable<T>. Bedeutet das, dass wenn ich tragen alle nachfolgenden Abfragen auf die IEnumerable<T> Objekt, das es tatsächlich die Operationen auf der Datenbank und nur die Rückkehr des Ergebnisse (weil das Objekt ist ein IQueryable in diesem Fall)? Oder,
  2. Nur die Where - Klausel, die übergeben wird in der Find Methode ausgeführt, der die Datenbank und alle nachfolgenden Abfragen, die ausgeführt werden, auf die IEnumerable<T> - Objekt auf dem client ausgeführt werden. Oder,
  3. Keines von beiden geschehen, und ich habe Total falsch verstanden, wie IEnumarable<T>, IQueryable<T> und Linq funktioniert.

Update:

Ich bin eigentlich ziemlich überrascht über die Antworten, die ich erhalten haben, in die Kommentare. Meine original-repository zurückgegeben IQueryable und weitere Forschung führte mich zu glauben, das war eine schlechte Sache zu tun (z.B. wenn mein viewModel akzeptiert ein repository, in dessen Konstruktor aufgerufen werden, jede Abfrage, die es will, das macht es schwieriger ist zu testen).

Alle Lösungen, die ich gesehen habe, so weit einzubeziehen, erstellen von entity-spezifische repositories, so dass IQueryable ist nicht ausgesetzt (Der einzige Unterschied, den ich denke, ist, dass ich Tue dies, in einer Allgemeinen Weise).

  • Soweit ich das beurteilen kann, alles aber IQueryable<T> erfolgt über den Speicher. Ich würde zurück IQueryable<T> statt IEnumerable<T> können Sie immer von IQueryable<T> zu IEnumerable<T> wenn Sie fertig sind mit der Filterung. Und sowieso, wenn Sie einem Zu.Liste() oder beim Durchlaufen der IQueryable<T> geht es automatisch als IEnumerable<T>.
Schreibe einen Kommentar