Wie sollte ich das Repository-Muster für komplexe Objektmodelle implementieren?


21

Unser Datenmodell umfasst fast 200 Klassen, die in etwa ein Dutzend Funktionsbereiche unterteilt werden können. Es wäre schön gewesen, Domains zu verwenden, aber die Trennung ist nicht so sauber und wir können sie nicht ändern.

Wir überarbeiten unser DAL, um Entity Framework zu verwenden, und die meisten Empfehlungen, die ich gesehen habe, empfehlen die Verwendung eines Repository-Musters. Keines der Beispiele befasst sich jedoch wirklich mit komplexen Objektmodellen. Einige Implementierungen, die ich gefunden habe, schlagen die Verwendung eines Repository pro Entität vor. Dies erscheint für große, komplexe Modelle lächerlich und nicht wartbar.

Ist es wirklich erforderlich, für jede Operation ein UnitOfWork und für jede Entität ein Repository zu erstellen? Ich könnte mit Tausenden von Klassen enden. Ich weiß, dass dies nicht zumutbar ist, aber ich habe nur sehr wenige Anleitungen zum Implementieren von Repository, Unit Of Work und Entity Framework für komplexe Modelle und realistische Geschäftsanwendungen gefunden.

Antworten:


6

Zuerst durchlaufen Sie jede Entität, die Sie haben, und fragen sich:

Ist es sinnvoll, diese Entität alleine beizubehalten?

Ich meine hier, dass in Ihrem Objektmodell einige Entitäten wahrscheinlich in anderen in einer Master-Detail-Beziehung enthalten sind. Wenn Ihre Entität stark von einer anderen abhängig ist, erstellen Sie kein Repository nur für diese Entität, da es wahrscheinlich nicht von selbst bestehen bleibt. Stattdessen erstellen Sie ein Repository für jede übergeordnete Klasse und stellen sicher, dass die untergeordneten Entitäten und andere Beziehungen gleichzeitig beibehalten werden.

Mir gefällt nicht, wie sie das UnitOfWork-Muster in dem von Ihnen bereitgestellten Link implementiert haben. Ich schlage vor, dass Sie mehr in diese Richtung tun . Sie müssen nicht eine Klasse pro Repository definieren. Dieselbe Klasse kann für jedes Repository verwendet werden, wobei jedes für die Lebensdauer des Vorgangs eine eigene Instanz der UnitOfWork-Klasse hat. Sie können dasselbe UnitOfWork auch in verschiedenen Repositorys für Änderungen wiederverwenden, die Sie gleichzeitig beibehalten möchten.


Netter Link! Ich überprüfe es.
Eric Falsken

Ihr Link (und Ihre Antwort) waren am hilfreichsten, obwohl ich nicht die angegebenen Muster verwendet habe. Am Ende verwendete ich eine Wrapper-Klasse, die die Add / Attach / Remove / SaveChanges-Methoden als Proxy für ein generisches Repository verwendete, und fügte dann eine Query / QuerySingle / QueryAll-Methode hinzu, die benutzerdefinierte Abfrageklassen für meine Abfrageimplementierung akzeptiert. Dies funktioniert sehr gut, sodass ich sowohl LINQ- als auch T-SQL-Abfragen ausführen kann, ohne EF direkt einzubeziehen.
Eric Falsken

Das Entity Framework mit seiner Verwendung von Transaktionen ist bereits eine Implementierung des Unit of Work-Musters.
Greg Burghardt

1
Link ist tot ...
Newtopian

3

Vielleicht sollten Sie einen Blick auf Domain-Driven Design werfen . Es wird empfohlen, Ihre Objekte in Aggregaten zu gruppieren und Repositorys nur für die Stammentität jedes Aggregats zu erstellen. Es ist ein guter Weg, um Ordnung in ein großes komplexes Objektmodell zu bringen.

Ihre verschiedenen Funktionsbereiche könnten begrenzte Kontexte sein . Es gibt verschiedene Techniken , um mit überlappenden begrenzten Kontexten umzugehen, wenn die Trennung zwischen ihnen nicht klar ist.


0

Welche theoretische Grundlage haben Sie für das Datenbankdesign "Repository-Muster" gefunden? Ich vermute keine. Es ist eine Schicht von Komplexität, die auf einer falschen Prämisse beruht: dass die "Persistenzschicht" etwas ist, von dem Sie isoliert werden müssen. Soweit ich das beurteilen kann, spielt es eine Rolle, die Unkenntnis der relationalen Entwurfsprinzipien in der Programmierung zu verbreiten und die vorausgesetzte Zentralität des OO-Entwurfs der Anwendung zu beeinträchtigen. Aber es rechtfertigt seine Existenz nicht aus rationalen, geschweige denn theoretischen Gründen.

Der einzig wahre Weg zum Datenbankdesign hat sich in 30 Jahren nicht geändert: Analysieren Sie die Daten. Finden Sie die Schlüssel und Einschränkungen und viele-zu-eins-Beziehungen. Gestalten Sie Ihre Tische nach Boyce-Codd Normalform. Verwenden Sie Ansichten und gespeicherte Prozeduren, um den Datenzugriff zu erleichtern.

Ein SQL-DBMS bietet eine bessere Isolationsschicht als alles, was der Programmierer bieten kann. Wenn sich die Datenbank ändert, muss sich möglicherweise auch die für den Zugriff verwendete SQL ändern. Beachten Sie jedoch, dass dies unabhängig davon gilt, ob es eine Vermittlungsebene gibt oder nicht . Solange die Anwendung Ansichten und gespeicherte Prozeduren verwendet, um auf das DBMS zuzugreifen, zeigen gewöhnliche SQL-Engineering-Tools an, wenn Änderungen an der zugrunde liegenden Datenbank diese Ansichten und gespeicherten Prozeduren ungültig machen.

Darin liegt natürlich die Herausforderung. Eine Vermittlungsebene vermittelt dem Programmierer die Illusion von Isolation und den Komfort, Code zu schreiben, den er zu tun weiß. Das Erlernen von Datenbankdesign und SQL erfordert das Erlernen von etwas Neuem. Die meisten Menschen würden lieber sterben als denken, und viele haben Erfolg.

Jemand in Ihrem Team wird zweifellos beanstanden, dass das Schreiben von SQL zur Unterstützung Ihrer 200 Klassen eine Menge Arbeit ist. Ohne Zweifel. Aber zumindest ist es nützliche Arbeit. Wenn Sie eine Datenbank entwerfen, indem Sie Ihr OO-Design imitieren, werden Sie auch viel Arbeit erledigen, viel davon unbrauchbar, und das meiste, was das DBMS Ihnen bietet, zunichte machen.

Beispielsweise erwägen Sie, die Arbeitseinheit in der Datenbank wiederzugeben (vermutlich als Tabelle oder als Tabellen). Arbeitseinheit ist eine integrierte Service des DBMS: begin transaction... Update - Datenbank ... commit transaction. Nichts zu modellieren, außer die Zuordnung Ihrer Klassen zu den Datenbanktabellen in SQL.

Ihre Frage wurde vor 4 Jahren gestellt. Ich antworte, weil es in letzter Zeit auf irgendeine Weise "aktualisiert" wurde, was darauf hinweist, dass es für jemanden immer noch von Interesse ist. Ich hoffe, dass meine Antwort den Leser ermutigt, die grundlegende relationale Theorie auf das Problem anzuwenden, anstatt eine sinnlose Problemumgehung anzuwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.