Ich glaube, wenn Sie Ihre Repositorys haben, verwenden Sie ein ORM, das bereits genug von der Datenbank abstrahiert ist.
Wo ich jetzt arbeite, glaubt jedoch jemand, dass wir eine Ebene haben sollten, die das ORM abstrahiert, falls wir das ORM später ändern möchten.
Ist es wirklich notwendig oder ist es einfach viel Aufwand, eine Ebene zu erstellen, die auf vielen ORM funktioniert?
Bearbeiten
Nur um mehr Details zu geben:
- Wir haben POCO-Klasse und Entity-Klasse, die mit AutoMapper zugeordnet sind. Entitätsklassen werden von der Repository-Schicht verwendet. Die Repository-Schicht verwendet dann die zusätzliche Abstraktionsebene, um mit Entity Framework zu kommunizieren.
- Die Geschäftsschicht hat in keiner Weise direkten Zugriff auf Entity Framework. Auch ohne die zusätzliche Abstraktionsebene über das ORM muss diese die Serviceschicht verwenden, die die Repository-Schicht verwendet. In beiden Fällen ist die Geschäftsschicht vollständig vom ORM getrennt.
- Das Hauptargument ist, ORM in Zukunft ändern zu können. Da es wirklich in der Repository-Schicht lokalisiert ist, ist es für mich bereits gut getrennt und ich verstehe nicht, warum eine zusätzliche Abstraktionsebene erforderlich ist, um einen "Qualitäts" -Code zu haben.
Antworten:
Auf diese Weise liegt der Wahnsinn. Es ist sehr unwahrscheinlich, dass Sie jemals ORMs ändern müssen. Und wenn Sie sich jemals dazu entschließen, das ORM zu ändern, machen die Kosten für das Umschreiben der Zuordnungen einen winzigen Bruchteil der Kosten für die Entwicklung und Pflege Ihres eigenen Meta-ORM aus. Ich würde erwarten, dass Sie ein paar Skripte schreiben können, um 95% der Arbeit zu erledigen, die zum Wechseln von ORMs erforderlich ist.
Inhouse-Frameworks sind fast immer eine Katastrophe. Der Bau eines solchen im Vorgriff auf zukünftige Bedürfnisse ist fast eine garantierte Katastrophe. Erfolgreiche Frameworks werden aus erfolgreichen Projekten extrahiert und nicht im Voraus erstellt, um imaginären Anforderungen gerecht zu werden.
quelle
Das ORM bietet eine Abstraktion für Ihre Datenschicht, die unabhängig von ihrem RDBMS ist. Es reicht jedoch möglicherweise nicht aus, Ihre Geschäftsschicht von Ihrer Datenschicht zu "lösen". Insbesondere sollten Sie nicht zulassen, dass Objekte, die RDBMS-Tabellen zugeordnet sind, direkt in die Geschäftsschicht "gelangen".
Zumindest muss Ihre Geschäftsschicht auf Schnittstellen programmieren, die Ihre ORM-verwalteten, tabellenabgebildeten Objekte aus der Datenschicht möglicherweise implementieren könnten. Darüber hinaus müssen Sie möglicherweise eine schnittstellenbasierte Ebene für die Erstellung abstrakter Abfragen erstellen, um die nativen Abfragefunktionen Ihres ORM auszublenden. Das Hauptziel besteht darin, zu vermeiden, dass ein bestimmtes ORM über die Datenschicht hinaus in Ihre Lösung "eingebrannt" wird. Beispielsweise könnte es verlockend sein, HQL- Zeichenfolgen ( Hibernate Query Language ) in der Geschäftsschicht zu erstellen . Diese scheinbar unschuldige Entscheidung würde jedoch Ihre Geschäftsschicht an den Ruhezustand binden und so die Geschäfts- und die Datenzugriffsschicht zusammenbringen. Sie sollten versuchen, diese Situation so weit wie möglich zu vermeiden.
BEARBEITEN: In Ihrem Fall ist die zusätzliche Schicht im Repository Zeitverschwendung: Basierend auf Ihrem zweiten Punkt ist Ihre Geschäftsschicht ausreichend von Ihrem Repository isoliert. Das Bereitstellen einer zusätzlichen Isolierung würde zu unnötiger Komplexität ohne zusätzliche Vorteile führen.
Das Problem beim Erstellen einer zusätzlichen Abstraktionsschicht in Ihrem Repository besteht darin, dass die bestimmte "Marke" von ORM die Art und Weise bestimmt, wie Sie damit interagieren. Wenn Sie einen dünnen Wrapper erstellen, der wie Ihr ORM aussieht, aber unter Ihrer Kontrolle steht, ist das Ersetzen des zugrunde liegenden ORM ungefähr so schwierig wie ohne diese zusätzliche Ebene. Wenn Sie andererseits eine Ebene erstellen, die Ihrem ORM nicht ähnelt, sollten Sie Ihre Wahl der objektrelationalen Zuordnungstechnologie in Frage stellen.
quelle
Die UnitOfWork stellt normalerweise diese Abstraktion bereit. Es ist ein Ort, der geändert werden muss. Ihre Repositorys hängen über eine Schnittstelle davon ab. Wenn Sie jemals O / RM ändern müssen, implementieren Sie einfach eine neue UoW darüber. Eins und fertig.
Übrigens geht es über das reine Umschalten von O / RM hinaus. Denken Sie an Unit-Tests. Ich habe drei UnitOfWork-Implementierungen, eine für EF, eine für NH (weil ich die O / RMs während des Projekts für einen Client wechseln musste, der Oracle-Unterstützung wünschte) und eine für InMemory-Persistenz. Die InMemory-Persistenz war perfekt für Unit-Tests oder sogar für Rapid Prototyping, bevor ich bereit war, eine Datenbank dahinter zu stellen.
Das Framework ist einfach zu implementieren. Zuerst haben Sie Ihre generische IRepository-Schnittstelle
Und die IUnitOfWork-Oberfläche
Als nächstes folgt das Basis-Repository (Sie entscheiden, ob es abstrakt sein soll oder nicht
Die Implementierung von IUnitOfWork ist für EF, NH und In Memory ein Kinderspiel. Der Grund, warum ich IQueryable zurückgebe, ist der gleiche Grund, den Ayende in seinem Beitrag erwähnt hat. Der Client kann das Ergebnis mithilfe von LINQ weiter filtern, sortieren, gruppieren und sogar projizieren, und Sie profitieren weiterhin davon, dass alles serverseitig ausgeführt wird.
quelle