8

Ich kämpfe ein bisschen mit Repositories. Ich benutze C# und NHibernate. Die Frage, die ich habe, ist: Wie viel sollte mein Repository tun, bevor es ein Speichern oder ein Holen aufruft?Wie viel Logik sollte ich meine Repository-Methoden bei der Verwendung von Repository-Muster setzen?

Zum Beispiel habe ich eine Benutzerklasse, die eine aggregierte Wurzel ist. Ich möchte eine Methode namens "register" aufrufen, die den Benutzer hinzufügt und einige Standardwerte basierend auf Geschäftsregeln setzt und einige andere Entitäten erstellt, die auch Unterteile des "Benutzer" -Stamms sind (dh Adresse, Gruppen usw.). Sollte ich nennen

userRepo.Register(newUser); 

was wäre (die offensichtlichen Probleme zu ignorieren):

Regsiter(User newUser){ 
newUser.SomeProp = "Default Data"; 
Group g= new Group; 
g.SomeProp2 = "Default Data"; 
newUser.Groups.Add(g); 
Session.Save(g); 
Session.Save(newUser); 
} 

oder sollte ich Register in einer Business-Schicht gesetzt haben und haben es tun:

Regsiter(User newUser){ 
newUser.SomeProp = "Default Data"; 
Group g= new Group; 
g.SomeProp2 = "Default Data"; 
newUser.Groups.Add(g); 
userRepo.Register(newUser, g);// this does session.save on both objects. 
} 

Both scheint etwas falsch zu sein.

Was ist der richtige Ansatz?

bearbeiten -------------------------------

Dank für alle Antworten. Ich kann nicht entscheiden, wer am richtigsten ist und daher welche Antwort zu akzeptieren.

Im Allgemeinen sagen alle die Geschäftsregeln in eine andere Schicht. das macht Sinn, aber ich bin unsicher über die Datenaufrufe für Gruppen - da Gruppen keine aggregierte Wurzel sind, sollten sie kein eigenes Repository haben. Wie gehe ich also vor, sie hinzuzufügen und zu speichern? In meinem Projekt wird beim Hinzufügen einer Gruppe zur Gruppensammlung des Benutzers die Gruppe in der Datenbank nicht automatisch erstellt. Ich muss auch session.save für das Objekt aufrufen. also lege ich das in den Benutzer Repo als userRepo.SaveGroup (g)?

Wenn ich eine createGroup() in der anderen Schicht habe, dann muss sie entweder ihr eigenes Repo oder die Benutzer verwenden. oder bin ich dick?

Antwort

3

Bestimmen Sie, wo Sie Ihre Register-Methode wollen, vielleicht in einer UserServices Klasse. Sie Objekterstellung zu einem Userfactory delegieren kann. in einem createNewUser (), richten Sie Ihre Standardeinstellungen für den Benutzer und die Groups-Sammlung ein und rufen Sie dann UserRepository.Save (newUser) auf, um die Daten persistent zu speichern.

// UserServices class 
public void Register(User newUser) 
{ 
    // add custom registration stuff. 
    _userRepository.Save(newUser); 
} 

// Application code 
User user = UserFactory.CreateNewUser(); 
_userServices.Register(user); 

// UserFactory 
public User CreateNewUser() 
{ 
    // all new user, group creation 
} 
+0

In diesem Beispiel befindet sich die Gruppenerstellung in der userfactory. Wo passiert die Gruppenbildung db Interaktion? in einer Gruppe Repo oder Benutzer Repo? –

+0

Kommt drauf an. Es kann einen Fall für ein Gruppen-Repository geben. Versuchen Sie in der Praxis, Repositorys auf einen pro Gesamtsystemstamm zu beschränken. Verwenden Sie in einem solchen Fall ein GroupRepository, um eine vorhandene Gruppe zu finden und die Gruppe als Parameter an die UserFactory.CreateNewUser-Methode zu übergeben. Wenn das UserRepository den Benutzer speichert, überprüfen Sie Ihre Konfiguration, um sicherzustellen, dass Sie auch die Gruppenzuordnung speichern. –

+1

Alternativ kann es sinnvoller sein, ein neues User-Objekt zu instanziieren und eine UserServices.RegisterWithDefaultGroup (User user) -Methode mit der folgenden Implementierung zu verwenden: Group defaultGroup = _groupRepository.FindByName ("Default"); user.AddGroup (defaultGroup); Registrieren (Benutzer); Es hängt wirklich von Ihrer Anwendung ab, von der Software-Architektur und davon, wie streng Sie bestimmte Prinzipien einhalten wollen. Viel Glück! –

6

Persönlich halte ich das Repository-Muster als Ersatz für Sprocs. So würde meine Repository Methoden wie getById(int id), save(), add(DomainObject obj) usw.

In einem Business-Tiere, würde ich userManager.registerUser (string Benutzername,/* params, usw. * /). Dies würde das Domänenobjekt erstellen. Diese Methode würde nur die Methode add() in der Datenebene aufrufen.

Kurz gesagt, die Business-Ebene ist Business-y, und die Datenebene ist Data-y.

+0

Basierend auf Ihren Methodennamen würde ich tatsächlich sagen, dass Ihre "Repositories" tatsächlich folgen das "Data Mapper" -Muster von Fowlers PofEAA Buch. Ein Repository von Domain Driven Design ist eine sammlungähnliche Schnittstelle und keine Klasse mit spezifischen Methoden. – jrista

3

Was ist Ihre Motivation für die Verwendung des Repository-Muster an erster Stelle? Normalerweise ist das Repository die Abstraktion Ihrer Objektpersistenzlogik. Es ruft Elemente von (normalerweise) einer Datenbank ab und behandelt auch Aktualisierungen, Einfügungen und Löschungen.

Wenn Sie einen Test geschrieben haben, um einige Logik zu überprüfen und nicht die Datenbank schlagen wollten, welche Objekte müssten Sie ausspionieren? Normalerweise das Repository.

In Szenario A) können Sie nicht testen, ob ein neuer Benutzer mit den korrekten Standarddaten erstellt wird, ohne direkt auf die Datenbank zu treffen.Aus diesem Grund würde ich befürworten, alle Geschäftslogik außerhalb der Repositorys zu halten und gehen Sie mit Ihrem zweiten Design

+0

Ein Repository sollte keine Updates verarbeiten. Es sollte den Datenzugriff auf Datenbanken (oder andere Persistenzen) in einer Sammlung wie der Schnittstelle abstrahieren. Eine normale Dotnet-Sammlung wie Liste oder Wörterbuch muss nicht über Updates informiert werden. Auch kein Repository. – Paco

0

Ich sehe zwei potenzielle "Falschheit" Probleme (da Sie nicht wirklich angegeben, was Sie dachten, war falsch mit ihnen).

  1. Wenn das Problem dreht sich um die Gruppe in der Benutzerregistrierungsmethode zu speichern, oder den Benutzer in der Gruppe Methoden zu speichern, dann sollten Sie diese in verschiedene Methoden trennen. (dh Register() würde RegisterGroup() oder GetGroup() aufrufen

  2. Wenn das Problem um das Speichern von Dingen dreht, bevor der Benutzer wirklich bereit ist, Dinge konzeptionell zu speichern, dann verfolgen Sie, was sie hinzufügen wollten und warten bis der Gesamt-Wertung „speichern“ Verfahren vor der Inbetriebnahme eines diese Informationen in dem Speicher genannt werden.

1

In Ihrem Codebeispiel würde ich die Register-Methode als Serviceoperation bezeichnen. Als Serviceoperation würde es eher einem Service oder einer Geschäftskomponente als einem Repository angehören. Laut Evans (von DDD fame) ist ein Repository eine sammlungähnliche Schnittstelle zu Entitäten, die in Ihrer Datenbank gespeichert sind. Die allgemeine Idee ist, dass Sie Ihren Entitäten über ein Repository grundlegenden CRUD-ähnlichen Zugriff gewähren, um den Rest Ihres Codes von Datenzugriffsdetails auf niedrigerer Ebene wie einem ORM-Tool zu abstrahieren.

Für Ihr Beispiel mit Register ... würde Ihre Service-Methode die Eingabe validieren, das User-Objekt erstellen und dann Ihr Repository aufrufen, um Ihre neue Entität dem "Repository" hinzuzufügen (was eine Datenbank sein könnte). aber könnte auch etwas anderes sein ... soweit es um Ihre Domain geht, spielt es keine Rolle ... es ist nur ein Repository.)

+0

Liegt der Servicevorgang in einer Controller-Klasse oder in der Business-Schicht? Oder ist es das gleiche, was Sie in diesem Fall betrifft? –

+0

Nun, ich betrachte Controller als anders als Services. Ein Controller ist ein Zugangspunkt für menschliche Interaktion ...und im Allgemeinen sollten sie so leicht wie möglich sein. Ihre Controller sollten nur minimale Orchestrierung von Aufrufen für andere Dienste vornehmen, keine Daten packen und diese Daten in eine Ansicht leiten, mehr nicht. Ein Dienst kann ein Anwendungsdienst oder ein Unternehmensdienst sein. Anwendungsdienste können reine Arbeit auf Anwendungsebene ausführen oder mehrere Geschäftsdienste zusammenstellen ... aber ein Dienst ist der Bereich, in dem der Großteil Ihres Verhaltens liegt, einschließlich der Verwendung von Repositorys. – jrista

+1

@ Charlie Bear: Check out Jeffrey Palermo Zwiebel Architektur. Dies ist, was ich für DDD-ähnliche Apps verwende. Es kann helfen zu erklären, was wohin geht. Viel Glück! http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ –

Verwandte Themen