Frage

Ich habe die Erkundung BDD / DDD und als Folge versucht, mit einer ordnungsgemäßen Umsetzung der Repository-Muster zu entwickeln. Bisher es war schwer, einen Konsens über den besten Weg zu finden, diese zu implementieren. Ich habe versucht, es zu den folgenden Variationen einkochen, aber ich bin nicht sicher, was der beste Ansatz ist.

Als Referenz Ich baue eine ASP.MVC Anwendung mit NHibernate als Back-End.

public interface IRepository<T> {
        // 1) Thin facade over LINQ
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IQueryable<T> Find();
        // or possibly even
        T Get(Expression<Func<T, bool>> query);
        List<T> Find(Expression<Func<T, bool>> query);
}

public interface IRepository<T> {
        // 2) Custom methods for each query
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> FindBySku(string sku);
        IList<T> FindByName(string name);
        IList<T> FindByPrice(decimal price);
        // ... and so on
}

public interface IRepository<T> {
        // 3) Wrap NHibernate Criteria in Spec pattern
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> FindBySpec(ISpecification<T> specification);
        T GetById(int id);
}


public interface IRepository<T> {
        // 4) Expose NHibernate Criteria directly
        T GetById(int id);
        void Add(T entity);
        void Update(T entity);
        void Remove(T entity);
        IList<T> FindAll();
        IList<T> Find(ICriteria criteria);
        // .. or possibly
        IList<T> Find(HQL stuff);
}

Meine ersten Gedanken sind, dass

1) ist groß von einer Wirkungsgrad Sicht, aber ich kann in Schwierigkeiten geraten, wie die Dinge komplizierter.

2) scheint sehr mühsam und konnte mit einer sehr überfüllten Klasse am Ende, aber ansonsten bietet einen hohen Grad an Trennung zwischen meiner Domain-Logik und Datenschicht, die Ich mag.

3) scheint schwierig vorne und mehr Arbeit Abfragen zu schreiben, aber Grenzen überqueren Kontamination nur die Specs Schicht.

4) Meine wenigsten, aber vielleicht direkteste Implementierung und möglicherweise die meisten Datenbank effizient für komplexe Abfragen, obwohl es eine große Verantwortung auf dem anrufenden Code setzt.

War es hilfreich?

Lösung

Ich glaube, sie sind alle gute Möglichkeiten (außer vielleicht 4, wenn Sie sich nhibernate nicht binden wollen), und Sie scheinen ihre Vor- und Nachteile haben auch analysiert, um eine Entscheidung auf eigene Faust auf der Grundlage Ihrer aktuellen Unterfangen. schlagen Sie sich nicht zu hart daran.

Im Moment arbeite ich an einer Mischung zwischen 2 und 3 Ich denke,:

public interface IRepository<T> 
{
        ...
        IList<T> FindAll();
        IList<T> FindBySpec(ISpecification<T> specification);
        T GetById(int id);
}

public interface ISpecificRepository : IRepository<Specific> 
{
        ...
        IList<Specific> FindBySku(string sku);
        IList<Specific> FindByName(string name);
        IList<Specific> FindByPrice(decimal price);
}

Und es gibt auch einen Repository (T) Basisklasse.

Andere Tipps

Es gibt auch ein gutes Argument für ein „keine der oben genannten“ -Ansatz.

Das Problem mit Generika-Repositories ist, dass Sie die Annahme machen, dass alle Objekte in Ihrem System werden alle vier CRUD-Operationen unterstützen: Erstellen, Lesen, Aktualisieren, Löschen. Aber in komplexen Systemen, werden Sie wahrscheinlich Objekte, die nur einige der Operationen unterstützen. Zum Beispiel könnten Sie haben Objekte, die schreibgeschützt ist, oder Objekte, die erstellt werden, aber nie aktualisiert.

Sie konnten die IRepository Schnittstelle in kleine Schnittstellen brechen, für Lesen, Löschen, etc., aber das ist ziemlich schnell chaotisch wird.

Gregory Junge ein gutes Argument macht (von DDD / Software Schichtung Perspektive), dass jedes Repository sollte nur die Operationen unterstützen, die auf das Domain-Objekt spezifisch sind oder aggregieren Sie arbeiten mit. Hier ist sein Artikel über .

Und für eine alternative Ansicht, sehen diese Ayende Blog-Post .

Eines der Dinge, die wir tun, ist, dass alle unsere Repositories haben unterschiedliche Bedürfnisse, so dass wir eine Sammlung von Schnittstellen zu erstellen:

public interface IReadOnlyRepository<T,V>
{
   V Find(T);
}

In diesem Beispiel wird die Nur-Lese-Repository nur tut wird aus der Datenbank. Der Grund für die T, V ist die V darstellt, was durch das Repository zurückgeführt wird und die T repräsentiert, was in übergeben wird, so könnte man so etwas tun:

public class CustomerRepository:IReadOnlyRepository<int, Customer>, IReadOnlyRepository<string, Customer>
{
    public Customer Find(int customerId)
    {
    }

    public Customer Find(string customerName)
    {
    }
}

Ich kann auch separate Schnittstellen für das Hinzufügen, Aktualisieren und Löschen erstellen. Auf diese Weise, wenn mein Repository nicht das Verhalten braucht es nicht dann einfach nicht die Schnittstelle implementieren.

Ich bin ein Fan von bif 1, weil ich Filter und Paging-Erweiterungsmethoden schaffen kann, als ich auf die IQueryable <> Rückgabewerte für die Find-Methode anwenden können. Ich halte die Erweiterungsmethoden in der Datenschicht und dann im laufenden Betrieb in der Business-Schicht aufzubauen. (Nicht ganz rein, zugegebenermaßen.)

Natürlich, wenn das System stabilisiert ich die Möglichkeit haben, auf bestimmte Find-Methoden unter Verwendung der gleichen Erweiterungsmethoden zu machen und optimieren mit Func <>.

Wenn Ihr Repository unter Verwendung von NH mit Linq kann sein:

session.Linq<Entity>()

Die Spezifikationen sind Dinge, die mit umgehen:

IQueryable<Entity>

Sie können sie alle weg Fassade, wenn Sie wollen, aber das ist eine Menge weltlicher Arbeit zu abstrahieren einer Abstraktion.

Einfach ist gut. Yah, NH tut Datenbanken, aber es bietet so viel mehr Muster. Mit Ausnahme der DAL auf NH hängt weit von einer Sünde ist.

Ich glaube, es hängt von Ihren Bedürfnissen. Es ist wichtig, über Repository in Verbindung mit anderem Design-Muster zu denken, die Sie verwenden in Betracht ziehen. Schließlich hängt es sehr auf das, was erwarten Sie von Repository (was die Hauptgründe für die Verwendung von es sind).

Sie benötigen strenge Ebene erstellen (zum Beispiel müssen Sie NHibernate mit Entity Framework in der Zukunft ersetzen)? Wollen Sie Test vor allem für die Repository-Methoden schreiben?

Es gibt keine beste Art und Weise, wie Repository zu erstellen. Es gibt nur wenige Möglichkeiten, und es ist auf jeden Fall bis zu Ihnen, was für Ihre Bedürfnisse am praktischsten ist.

Wither das Repository

Ein relevanter Artikel von Jimmy Bogard von LosTechies

http: // www .lostechies.com / blogs / jimmy_bogard / Archiv / 2009/09/10 / welken-the-repository.aspx

Auch ein anderer Artikel schnell mit einigen Kommentaren Version # 2 was darauf hindeutet, ist wirklich ein DOA-Muster und kein Repository.

http://fabiomaulo.blogspot.com/2009/06 /linq-and-repository.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top