Wo sollte sich der Datenbank-Persistenzcode in einem MVC-System befinden?

21

Ich habe mehrere Konfigurationen für die Speicherung von Informationen in der Datenbank gesehen. Im Allgemeinen scheinen drei Arten von Designs in meiner Ecke der Welt üblich zu sein:

  • Der Controller verwaltet die Persistenz
  • Modell verwaltet die Persistenz
  • Die Bibliothek eines Drittanbieters verwaltet die Persistenz und erfordert normalerweise einige Anmerkungen zum Modell.

Ich frage mich, welche Konfiguration (falls vorhanden) konzeptionell am einfachsten zu verwenden / am kompatibelsten mit einer MVC-Architektur ist.

(Wenn es sich nicht um eine von mir aufgeführte handelt, geben Sie bitte einen kurzen Überblick als Teil der Antwort.)

Blaubeerfelder
quelle

Antworten:

13

Ihre zweite und dritte Option sind identisch. Das M in MVC ist nicht das Datenmodell, sondern das Domänenmodell. Dies schließt die Persistenz ein, ob direkt oder über ein ORM, und beide sind vollkommen korrekt.

Der Controller sollte den Datenfluss auf der Site verwalten und Daten an die Domäne weiterleiten (manchmal über eine Service-Schicht), um sie zu verarbeiten. Daher ist es falsch - oder zumindest semantisch unangenehm, darauf zu bestehen.

pdr
quelle
2
Ich bin bis zu einem gewissen Grad anderer Meinung. Konkrete Nutzung von Persistenz ist Anwendungslogik und gehört somit in eine Anwendungsschicht und nicht in die Domänenschicht. Die Domain-Schicht (die das Domain-Modell enthält) sollte die Persistenz des Casual Business-Programms nicht kennen. Der Controller ist ein Orchestrator . Es kann (Daten-) Dienste, die Benutzeroberfläche und das Domänenmodell orchestrieren.
Falcon
1
@Falcon: Während der Controller steuern sollte, wann Daten aus der Datenbank geladen und dort gespeichert werden, ist es in Ordnung, das Modell dazu anzuweisen. Die Verwendung eines ORM (Standard oder Roll-Your-Own) bedeutet normalerweise, dass das Modell zum Laden / Speichern aufgefordert wird, das dann an den ORM delegiert wird. Eine andere Möglichkeit besteht darin, dass der Controller einem ORM anweist, etwas zu laden / speichern, indem er ihm eine Modellklasse zum Laden (mit Auswahlkriterien) oder eine Modellinstanz zum Speichern übergibt. In beiden Fällen ist das tatsächliche Laden / Speichern eng mit dem Modell verbunden.
Marjan Venema
@ Marjan Venema: Ja, ich stimme zu, aber die Frage ist, wo dieser Code leben sollte. Ich bemühe mich, das Modell so persistenzunabhängig wie möglich zu halten und nur die Domänenentitäten mit ihrem Verhalten und ihren Interaktionen zu modellieren. Alles andere wird in Anwendungsebenen leben (da es sich um eine Anwendung meines Modells handelt). Mapping-Informationen / Datenzugriff sind vollständig vom Domain-Modell entkoppelt und können auch die Versionierung (Upgrade / Downgrade) übernehmen. Die Anwendung des Datenzugriffs befindet sich auch in Anwendungsebenen (die Dienste, Repositorys usw. enthalten)
Falcon
@ Falcon: Ja, das ist eine gute Methode, und so habe ich es in der Vergangenheit mit separaten Mapping-Klassen gemacht. Mit dem Aufkommen von erweitertem RTTI (Delphi) und Reflection (.Net und andere) habe ich jedoch keine Bedenken, diese in Verbindung mit der Annotation der Attribute des Business-Objektmodells zu verwenden, um alles zum Laufen zu bringen und nur Überladungen von Code-Hooks in und zu verwenden / oder speziell codierte Initialisierungsklassen für die Datenbankversionierung.
Marjan Venema
5

In der Realität handelt es sich bei MVC meistens um ein UI-Implementierungsmuster, daher ist die Frage etwas umstritten. Es gibt jedoch wirklich nur zwei große Optionen. Ihr Controller sendet normalerweise Anforderungen zum Laden oder Speichern von Entitäten in Ihrem Modell, indem er entweder 1) eine Dienstschicht oder 2) das Active Record-Muster verwendet.

Die Serviceschicht kann eine beliebige Anzahl von Formen annehmen, obwohl ich es persönlich vorziehen würde, mit einer Repository-Abstraktion für die aggregierten Stammentitäten zu arbeiten, deren konkrete Implementierungen entweder mit einer Art ORM oder einem einfachen DAO oder einer API für einen nicht relationalen Speicher, wenn dies für die Anwendung sinnvoll ist.

Das Active Record-Muster bedeutet, dass Ihr Modell für die Persistenz verantwortlich ist, obwohl es normalerweise bedeutet, dass eine Basisklasse die Zuordnungen zu Ihrem Geschäft verwaltet, sodass Ihr Modell nicht wirklich so direkt involviert ist.

Grundsätzlich sendet der Controller Anforderungen an persistente Objekte, unabhängig davon, ob dies ein Aufruf an Ihr Repository, Ihre UnitOfWork-Implementierung oder die Save-Methode für Ihre Entitäten ist. Wenn Sie Repositorys verwenden, sind Ihre Modellobjekte persistenzunabhängig.

JasonTrue
quelle
3

In einem MVC-System (Model-View-Controller) enthält das Modell die Daten. Ich glaube also, dass die Datenbankpersistenz drin sein sollte.

Nettogrof
quelle
2

Die meisten MVC-Beispiele auf hoher Ebene, die ich gesehen habe, haben eine separate infrastructureEbene, die den tatsächlichen Code für die Datenbankimplementierung enthält (dh die spezifischen Aufrufe von NHibernate oder EF oder Linq oder was auch immer Ihre Datenebene ist), während die Ebene "Modell" (häufig auch) Die "Domain" -Schicht enthält die Schnittstellen , die die Datendienste definieren.

Wayne Molina
quelle
0

Die Standardpraxis in MVC besteht darin, Datenstruktur und Persistenz in die M-Schicht (Odel-Schicht) aufzunehmen.

Die Modellebene enthält nicht nur die Klassen (POCOs usw.), die Sie in Ihrer Anwendung verwenden werden. Sie enthalten die Repositorys für diese Klassen.

Ein Beispiel wäre ein Repository, in dem Sie mehrere Datenklasseninstanzen haben, z.

Clients repository

AllClients()
RecentClients()
ClientByID(int id)

Sie können Ihre Modelldomäne viel besser organisieren und haben auf viele Arten Zugriff auf Ihre Daten. Die Daten- / Modellschicht ist jedoch kompakt und robust

Mihalis Bagos
quelle