it-swarm.com.de

Welches spezifische Problem löst das Repository-Muster?

(Hinweis: Meine Frage hat sehr ähnliche Bedenken wie die Person, die diese Frage gestellt hat vor drei Monaten, aber sie wurde nie beantwortet.)

Vor kurzem habe ich angefangen, mit MVC3 + Entity Framework zu arbeiten, und ich lese immer wieder, dass die beste Vorgehensweise darin besteht, das Repository-Muster zu verwenden, um den Zugriff auf die DAL zu zentralisieren. Dies wird auch von Erklärungen begleitet, dass Sie die DAL von der Domäne und insbesondere von der Ansichtsebene getrennt halten möchten. Aber in den Beispielen, die ich gesehen habe, gibt das Repository einfach DAL-Entitäten zurück (oder scheint zu sein), d. H. In meinem Fall würde das Repository EF-Entitäten zurückgeben.

Meine Frage ist also, was nützt das Repository, wenn es nur DAL-Entitäten zurückgibt? Fügt dies nicht eine Komplexitätsebene hinzu, die das Problem der Weitergabe von DAL-Entitäten zwischen Ebenen nicht beseitigt? Wenn das Repository-Muster einen "einzelnen Eintrittspunkt in die DAL" erstellt, wie unterscheidet sich das vom Kontextobjekt? Wenn das Repository einen Mechanismus zum Abrufen und Speichern von DAL-Objekten bietet, wie unterscheidet sich das vom Kontextobjekt?

Außerdem habe ich an mindestens einer Stelle gelesen, dass das Unit of Work-Muster den Repository-Zugriff zentralisiert, um die Datenkontextobjekte zu verwalten, aber ich weiß auch nicht, warum dies wichtig ist.

Ich bin mir zu 98,8% sicher, dass ich hier etwas vermisse, aber in meinen Lesungen habe ich es nicht gesehen. Natürlich lese ich möglicherweise nicht die richtigen Quellen ...: \

42
Dave

Die DbContext von Entity Framework ähnelt im Wesentlichen einem Repository (und auch einem Unit of Work). Sie müssen es nicht unbedingt in einfachen Szenarien abstrahlen.

Der Hauptvorteil des Repositorys besteht darin, dass Ihre Domäne unwissend und unabhängig vom Persistenzmechanismus sein kann. In einer schichtbasierten Architektur verweisen die Abhängigkeiten von der UI-Schicht über die Domäne (oder normalerweise als Geschäftslogikebene bezeichnet) auf die Datenzugriffsebene. Dies bedeutet, dass die Benutzeroberfläche von der BLL abhängt, die wiederum von der DAL abhängt.

In einer moderneren Architektur (die durch domänengesteuertes Design und andere objektorientierte Ansätze verbreitet wird) sollte die Domäne keine nach außen gerichteten Abhängigkeiten haben. Dies bedeutet, dass die Benutzeroberfläche, der Persistenzmechanismus und alles andere von der Domäne abhängen sollte und nicht umgekehrt.

Ein Repository wird dann über seine Schnittstelle innerhalb der Domäne dargestellt, seine konkrete Implementierung außerhalb der Domäne jedoch im Persistenzmodul. Auf diese Weise hängt die Domäne nur von der abstrakten Schnittstelle ab, nicht von der konkreten Implementierung.

Das ist im Grunde Objektorientierung gegenüber prozeduraler Programmierung auf architektonischer Ebene.

Siehe auch die Ports und Adapter a.k.a. Hexagonal Architecture .

Ein weiterer Vorteil des Repositorys ist, dass Sie ähnliche Zugriffsmechanismen für verschiedene Datenquellen erstellen können. Nicht nur für Datenbanken, sondern auch für Cloud-basierte Stores, externe APIs, Anwendungen von Drittanbietern usw.

21
Dennis Traub

Ich denke, der Begriff "Repository" wird allgemein so verstanden, wie das " Repository Pattern " durch das Buch Patterns der Enterprise Application Architecture von Martin Fowler beschrieben wird. 

Ein Repository vermittelt zwischen den Domänen- und Datenzuordnungsebenen. Verhält sich wie eine In-Memory-Domänenobjektsammlung. Client-Objekte Erstellen Abfragespezifikationen deklarativ und übermitteln diese zur Zufriedenheit an Repository. Objekte können dem Repository (.____.) Hinzugefügt und daraus entfernt werden, wie dies bei einer einfachen Sammlung von Objekten der Fall ist, und Der vom Repository eingekapselte Mapping-Code führt die entsprechenden Operationen aus hinter den Kulissen.

Auf der Oberfläche kann Entity Framework all dies erreichen und kann als einfache Form eines Repositorys verwendet werden. Ein Repository kann jedoch mehr als nur eine Datenschichtabstraktion enthalten. 

Nach dem Buch Domain Driven Design von Eric Evans hat ein Repository folgende Vorteile:

  • Sie bieten Kunden ein einfaches Modell, um Persistenzobjekte zu erhalten und ihren Lebenszyklus zu steuern
  • Sie entkoppeln Anwendungs- und Domänendesign von Persistenztechnologie, mehreren Datenbankstrategien oder sogar mehreren Datenquellen
  • Sie kommunizieren Designentscheidungen über den Objektzugriff
  • Sie ermöglichen den einfachen Austausch einer Dummy-Implementierung für Komponententests (normalerweise unter Verwendung einer In-Memory-Collection).

Der erste Punkt entspricht in etwa dem obigen Absatz, und es ist leicht zu erkennen, dass Entity Framework das problemlos selbst schafft. 

Einige würden argumentieren, dass EF auch den zweiten Punkt erreicht. Normalerweise wird EF jedoch einfach verwendet, um jede Datenbanktabelle in eine EF-Entität zu verwandeln und an die Benutzeroberfläche zu übergeben. Es mag den Mechanismus des Datenzugriffs abstrahieren, aber die relationale Datenstruktur hinter den Kulissen kaum abstrahieren. 

In einfacheren Anwendungen, die meistens datenorientiert sind, scheint dies kein wichtiger Punkt zu sein. Wenn die Domänenregeln/Geschäftslogik der Anwendungen jedoch komplexer wird, möchten Sie möglicherweise mehr objektorientiert . Es ist nicht ungewöhnlich, dass die relationale Struktur der Daten Besonderheiten enthält, die für die Geschäftsdomäne nicht wichtig sind, aber Nebeneffekte des Datenspeichers sind. In solchen Fällen reicht es nicht aus, den Persistenzmechanismus zu abstrahieren, sondern auch die Art der Datenstruktur. EF alleine hilft Ihnen normalerweise nicht dabei, aber eine Repository-Schicht wird dies tun.

Beim dritten Vorteil tut EF (aus Sicht der DDD) nichts, um zu helfen. Normalerweise verwendet DDD das Repository nicht nur, um den Mechanismus der Datenpersistenz zu abstrahieren, sondern auch, um Einschränkungen zu definieren, wie auf bestimmte Daten zugegriffen werden kann:

Wir benötigen auch keinen Abfragezugriff für persistente Objekte, die bequemer Durch Traversierung zu finden sind. Zum Beispiel könnte die Adresse einer Person Vom Objekt Person abgefragt werden. Und das Wichtigste: Jedes Objekt innerhalb eines AGGREGATEs darf nur durch Durchquerung von der Wurzel abgerufen werden.

Mit anderen Worten, Sie hätten kein 'AddressRepository', nur weil Sie eine Adressentabelle in Ihrer Datenbank haben. Wenn Ihr Design verwaltet, wie auf die Adressobjekte auf diese Weise zugegriffen wird, legen Sie im PersonRepository die Designauswahl fest und setzen diese durch.

Ein DDD-Repository würde sich normalerweise auch dort befinden, wo bestimmte Geschäftskonzepte, die sich auf Gruppen von Domänendaten beziehen, gekapselt werden. Ein OrderRepository verfügt möglicherweise über eine Methode namens OutstandingOrdersForAccount, die eine bestimmte Untermenge von Orders zurückgibt. Ein Kunden-Repository kann auch eine PreferredCustomerByPostalCode-Methode enthalten.

Die DataContext-Klassen von Entity Framework eignen sich für diese Funktionalität nicht ohne die hinzugefügte Repository-Abstraktionsschicht. Sie funktionieren gut für das, was DDD-Spezifikationen bezeichnet. Dies können einfache boolesche Ausdrücke sein, die an eine einfache Methode gesendet werden, die die Daten anhand des Ausdrucks auswertet und eine Übereinstimmung zurückgibt.

Was den vierten Vorteil angeht, gibt es zwar bestimmte Strategien, die den Datakontext ersetzen könnten, aber das Einbetten in ein Repository macht es ganz einfach.

In Bezug auf 'Unit of Work' muss das DDD-Buch Folgendes sagen:

Überlassen Sie die Transaktionssteuerung dem Client. Obwohl REPOSITORY in die Datenbank eingefügt wird und aus dieser gelöscht wird, schreibt sie normalerweise Nichts fest. Es ist verlockend, zum Beispiel nach dem Speichern Ein Commit auszuführen, aber der Client hat vermutlich den Kontext, um Arbeitseinheiten korrekt zu initiieren und Zu übernehmen. Das Transaktionsmanagement wird einfacher, wenn der REPOSITORY die Hände wegnimmt.

50
Eric King

Sie haben recht, in solchen einfachen Fällen ist das Repository nur ein anderer Name für ein DAO und bringt nur einen Wert: die Tatsache, dass Sie EF auf eine andere Datenzugriffstechnik umstellen können. Heute verwenden Sie MSSQL. Morgen benötigen Sie einen Cloud-Speicher. OR mit einem micro orm anstelle von EF oder dem Umschalten von MSSQL zu MySql.

In all diesen Fällen ist es gut, dass Sie ein Repository verwenden, da der Rest der App sich nicht darum kümmert, welchen Speicher Sie gerade verwenden.

Es gibt auch den eingeschränkten Fall, dass Sie Informationen aus mehreren Quellen (db + Dateisystem) erhalten, ein Repo fungiert als Fassade, aber es ist immer noch ein anderer Name für ein DAO.

Ein "reales" Repository ist nur gültig, wenn Sie mit Domänen-/Geschäftsobjekten arbeiten. Für datenorientierte Apps, die den Speicher nicht ändern, reicht der ORM alleine aus.

6
MikeSW

Dies ist in Situationen hilfreich, in denen Sie über mehrere Datenquellen verfügen und mit einer konsistenten Codierungsstrategie darauf zugreifen möchten.

Möglicherweise verfügen Sie über mehrere EF-Datenmodelle und einige Daten, auf die mit herkömmlichem ADO.NET mit gespeicherten Prozeduren zugegriffen wird, und einige Daten, auf die mit einer Drittanbieter-API zugegriffen wird, und einige, auf die von einer Access-Datenbank aus zugegriffen wird, die auf einem Windows NT4-Server unter einem Windows NT4-Server läuft Staubdecke in Ihrem Besenschrank.

Möglicherweise möchten Sie nicht, dass Ihre Unternehmens- oder Front-End-Layer sich darum kümmern, woher die Daten stammen. Erstellen Sie daher ein generisches Repository-Muster für den Zugriff auf "Daten" und nicht auf "Entity Framework-Daten".

In diesem Szenario unterscheiden sich Ihre tatsächlichen Repository-Implementierungen voneinander, aber der Code, der sie aufruft, würde den Unterschied nicht erkennen.

2
Joe Enos

In Ihrem Szenario würde ich mich einfach für eine Reihe von Schnittstellen entscheiden, die darstellen, welche Datenstrukturen (Ihre Domänenmodelle) von Ihrer Datenschicht zurückgegeben werden müssen. Ihre Implementierung kann dann eine Mischung aus EF, Raw ADO.Net oder einem anderen Datenspeicher/Provider sein. Die Schlüsselstrategie hierbei ist, dass die Implementierung vom unmittelbaren Konsumenten - Ihrer Domain-Schicht - abstrahiert wird. Dies ist nützlich, wenn Sie Ihre Domänenobjekte einem Komponententest unterziehen möchten und in seltenen Fällen Ihren Datenanbieter/Ihre Datenbankplattform vollständig ändern möchten.

Wenn Sie dies nicht bereits getan haben, sollten Sie die Verwendung eines IOC _container in Betracht ziehen, da diese die lockere Kopplung Ihrer Lösung durch Dependency Injection sehr einfach machen. Es stehen viele zur Verfügung , persönlich bevorzuge ich Ninject .

Die Domänenschicht sollte Ihre gesamte Geschäftslogik enthalten - die Regeln und Anforderungen der Problemdomäne - und können direkt von Ihrer MVC3-Webanwendung verwendet werden. In bestimmten Situationen ist es sinnvoll, ein Services Layer einzuführen, das über dem Domain-Layer liegt. Dies ist jedoch nicht immer erforderlich und kann für unkomplizierte Webanwendungen ein Übermaß sein.

2
Baldy

Zu beachten ist auch, dass selbst wenn Sie wissen, dass Sie mit einem einzelnen Datenspeicher arbeiten werden, es dennoch sinnvoll sein kann, eine Repository-Abstraktion zu erstellen. Der Grund ist, dass es eine Funktion gibt, die Ihre Anwendung benötigt, die Ihr ORM du Jour entweder schlecht ausführt (Leistung) oder gar nicht, oder Sie wissen nicht, wie Sie den ORM an Ihre Bedürfnisse anpassen lassen. 

Wenn Sie Ihren ORM mit einer durchdachten Repository-Schnittstelle verbinden, können Sie je nach Bedarf problemlos zwischen verschiedenen Technologien wechseln. In meinen Repositories ist es nicht ungewöhnlich, dass einige Methoden EF für ihre Arbeit verwenden und andere, um etwas wie PetaPoco oder (keuchen) ADO.net-Code zu verwenden. Mit der Repository-Abstraktion können Sie genau das richtige Werkzeug für die anstehende Aufgabe verwenden, ohne diese Komplexität in den Clientcode zu dringen. 

1
cdaq

Ich denke, es gibt ein großes Missverständnis darüber, was viele Artikel "Repository" nennen. Und deshalb gibt es Zweifel, welchen wirklichen Wert diese Abstraktionen haben.

Meiner Meinung nach ist das Repository in seiner reinen Form IEnumerable, während Sie und viele Artikel über "Datenzugriffsdienst" sprechen.

Ich habe darüber gebloggt hier .

0
Michael Logutov