it-swarm.com.de

Ist Unit Of Work und Repository Patterns für große Projekte sehr nützlich?

Ich starte ein neues Webprojekt mit ASP.NET Webforms + EF4. Ich versuche, anhand dieses Lernprogramms ein Repository-Muster mit einem Muster für Arbeitseinheiten anzuwenden: http://www.dotnetage.com/publishing/home/2011/07/05/6883/the-repository-pattern-with -ef-code-first-dependeny-injection-in-asp-net-mvc3.html

Ich glaube, ich hatte die Idee, aber meine Frage ist, ob ich beim Erstellen eines neuen Objekts im Modell dieses Objekt auch in IDALContext der Unit Of Work definieren muss. Ist das nicht ein Handbruch für eine schnelle Entwicklung? Auch wenn Sie mit mehreren Entwicklern zusammenarbeiten und nicht möchten, dass andere Entwickler Ihre DAL sehen, wie können Sie dies verwalten? Denn in diesem Muster müssen Sie, wie ich verstehe, beim Erstellen eines neuen Objekts im Modell dieses Tutorial auch im IDALContext definieren. Tut mir leid, dass ich so verwirrt bin.

24
mehmetserif

Martin Fowler beschreibt die Rolle des Repository wie folgt: "Ein Repository vermittelt zwischen der Domänen- und der Datenzuordnungsschicht und verhält sich wie eine speicherinterne Domänenobjektsammlung." Was in Entity Framework 4.1 verfügbar gemacht wird, ist ein Repository in diesem Sinne. Auch EF hat eine Einheit der Arbeit eingebaut. Mein Rat ist also, den Blog-Artikel, den Sie in Ihrer Frage erwähnt haben, zu ignorieren.

Code wie dieser ist nicht nur nutzlos oder wertlos, sondern auch gefährlich, denn es gibt keinen zusätzlichen Vorteil für Ihren Code, sondern eine Abhängigkeit!

public interface IUnitOfWork:IDisposable
{
    int SaveChanges();
}

public interface IDALContext : IUnitOfWork
{
    ICategoryRepository Categories { get; }
    IProductRepository Products { get; }
}

Um Ihre Frage mit einer Abstraktion zu beantworten, die zwischen der Domänen- und der Datenzuordnungsschicht vermittelt, ist es für "große" Projekte ein Muss, sich wie eine In-Memory-Domänenobjektsammlung zu verhalten. Wenn Sie einen UnitOfWork-Mechanismus unter der Haube haben, können Sie Ihre Geschäftslogik vom Zugriff auf eine Datenzugriffsabstraktion entkoppeln.

TL; TR; Repository und UnitOfWork können Ihnen helfen, aber wenden Sie es nicht wie im angegebenen Blog-Beitrag an.

18
saintedlama

Nun sollte die erste Frage lauten: Warum brauche ich überhaupt ein Repository oder ein Muster für Arbeitseinheiten? Könnte ich nicht einfach den EF-Kontext des Controllers verwenden, um die benötigte Abfrage direkt zu schreiben und die Daten zurückzugeben?
Antwort: Sie könnten, aber die eigentliche Absicht dahinter ist die Testbarkeit und damit eine höhere Qualität, einen besser wartbaren Code. Wenn Sie Ihren Datenzugriff trennen und ihn auf einen Ort konzentrieren, können Sie ihn während des Tests ausspotten. Auf diese Weise können Sie die in Ihrer Steuerung definierte Logik mit unit testen, ohne effektiv in einen Datenspeicher schreiben zu müssen.

Bevor Sie mit der Unit of Work beginnen, werfen Sie einen Blick auf das Repository-Muster . Dies abstrahiert im Wesentlichen den Datenzugriff für eine bestimmte Entität. So definieren Sie Methoden wie Filter (), All (), Update (..), Insert (..), Delete (...) und schließlich Save (). Tatsächlich können die meisten davon leicht zu einer BaseRepository<TEntity> -Klasse abstrahiert werden, sodass Sie in seltenen Fällen mit speziellem Verhalten nur ein neues Repository erstellen müssen. Sonst wäre es so etwas wie BaseRepository<Person> personRepo = new BaseRepository<Person>() oder BaseRepository<Address> addressRepo = new BaseRepository<Address>() etc.

Warum wird die Arbeitseinheit benötigt?
Eine Arbeitseinheit stellt alle Vorgänge dar, die in einem bestimmten Zyklus in einer Webumgebung normalerweise per HTTP-Anforderung ausgeführt wurden. Das bedeutet, wenn eine neue Anfrage eingeht, instanziiert man eine neue Arbeitseinheit, fügt neue Sachen hinzu, aktualisiert oder löscht sie und "schreibt" dann die Änderungen fest, indem man die .save()oder .commit() aufruft. Wenn Sie sich Entity Framework DbContext (oder ObjectContext) genauer ansehen, handelt es sich tatsächlich bereits um eine Arbeitseinheit.
Wenn Sie es jedoch weiter abstrahieren möchten, weil Sie Ihren EF-Kontext nicht unbedingt in Ihren Controller-Klassen haben möchten (denken Sie daran: Testbarkeit), erstellen Sie eine UoW, um Ihre Repositorys zu gruppieren und auch um sicherzustellen, dass sie vorhanden sind Alle verwenden dieselbe EF-Kontextinstanz. Letzteres können Sie auch über einen DI-Container (Dependency Injection Container) erreichen.

Zu Ihren Fragen: Ist es in großen Projekten nützlich? :
Auf jeden Fall, besonders in big Projekten. Es geht darum, die Verantwortlichkeiten getrennt zu halten (Datenzugriff, Geschäftslogik, Domänenlogik) und damit die Dinge testbar zu machen.

95
Juri

Software-Design-Patterns wurden entwickelt, um bestimmte Probleme mit dem richtigen Kontext zu lösen. Bei unsachgemäßer Verwendung führen sie zu unnötiger Komplexität, ohne dass Werte angegeben werden.

Welche Probleme soll das Repository-Muster lösen?

1- Minimierung der Logik für doppelte Abfragen : In großen Anwendungen werden möglicherweise viele komplexe LINQ-Abfragen an einigen Stellen dupliziert. In diesem Fall können Sie das Repository-Muster verwenden, um diese Abfragen zu kapseln und Doppelarbeit zu minimieren.

2- Bessere Trennung von Bedenken: Stellen Sie sich eine komplexe Abfrage vor, um die meistverkauften Kurse in einer bestimmten Kategorie zu erhalten, die eifriges Laden, Verbinden, Gruppieren, Filtern usw. beinhalten.

Wenn Sie so große komplexe Abfragen in Ihren Diensten/Controllern implementieren, erhalten Sie umfangreiche Dienste/Controller. Diese Klassen sind schwer zu testen, da sie viel lautes Stubben erfordern. Ihre Unit-Tests werden lang, fett und unerreichbar.

Wenn Sie mit diesem Problem konfrontiert sind, ziehen Sie möglicherweise die Verwendung des Repository-Musters in Betracht. In diesem Beispiel können wir die komplexe Abfrage kapseln, um die meistverkauften Kurse in einem Repository abzurufen:

courseRepository.GetTopSellingCourses(int categoryId, int count);

Auf diese Weise übernimmt Ihr Dienst/Controller nicht mehr das eifrige Laden, Beitreten, Gruppieren usw. Stattdessen werden sie an das Repository delegiert. Denken Sie daran, dass eifriges Laden, Verbinden und Gruppieren usw. die Logik abfragt und zu Ihrer Datenzugriffsebene gehört, nicht zu Ihren Diensten oder zur Präsentationsschicht.

3- Entkoppeln Ihrer Anwendungsarchitektur von Persistenz-Frameworks: Wenn Sie Entity Framework-Klassen (z. B. DbContext, DbSet usw.) direkt in Ihrer Anwendung verwenden, ist Ihre Anwendung eng mit Entity Framework verbunden. Wenn Sie zu einem späteren Zeitpunkt auf ein anderes O/RM oder sogar eine neuere Version von Entity Framework mit einem anderen Modell wechseln möchten, müssen Sie möglicherweise viele Teile Ihrer Anwendung ändern. Dies kann zu neuen Fehlern in Ihrer Anwendung führen. Sie können das Repository-Muster verwenden, um Ihre Anwendungsarchitektur von Persistenz-Frameworks wie Entity Framework zu entkoppeln. Auf diese Weise haben Sie die Freiheit, mit minimaler Auswirkung auf Ihre Anwendung zu einem anderen O/RM zu wechseln.

Schauen Sie sich dieses Video für weitere Details an:

https://youtu.be/rtXpYpZdOzM

2
Mosh

Sie sollten "Befehls-/Abfrageobjekte" als Alternative in Betracht ziehen. In diesem Bereich finden Sie eine Reihe interessanter Artikel, aber hier ist ein guter:

https://rob.conery.io/2014/03/03/repositories-and-unitofwork-are-not-a-good-idea/

Sie würden sich an ein einzelnes Befehlsobjekt pro Befehl halten, um einfache Transaktionen zu ermöglichen und die Komplexität des Musters der Arbeitseinheit zu vermeiden.

Wenn Sie jedoch der Meinung sind, dass ein Abfrageobjekt pro Abfrage überflüssig ist, können Sie durchaus 100% richtig liegen. Häufig können Sie sich dafür entscheiden, mit einem 'FooQueries'-Objekt zu beginnen, das im Wesentlichen ein Repository ist, jedoch nur für Abfragen. "Foo" könnte Ihr "Domain-Aggregat" im DDD-Sinne sein.

Möglicherweise finden Sie später einzelne Abfrageobjekte, die sich lohnen.

Wie bei den meisten Dingen müssen Sie System für System berücksichtigen.

0
Darren