Lazy Loading of Collection - Wie bekomme ich die Gegenstände?

7

Ich habe eine einfache Klasse, die ein einfaches POCO sein soll - sie enthält nur Daten. Mit einer Ausnahme: Es enthält eine Sammlung von Notizen. Ich möchte diese Sammlung lazy-load, so dass ich die Hinweise auf Seiten, die sie nicht benötigen, nicht abrufen muss. Der Stummel dafür ist das:

%Vor%

Nun, ich frage mich, wie ich von hier fortfahren soll. Es ist eine ASP.net MVC-Anwendung und ich verwende Dependency Injection, um die IRepositories in Klassen zu injizieren, die sie benötigen, zum Beispiel meine Controller. Aber da diese Klasse hier ein wirklich einfaches DTO sein soll, zögere ich, ein INoteRepository einzuschleusen, auch weil der Anrufer sich nicht darum kümmern oder sich darum kümmern sollte, dass dies lazy-loaded ist.

Ich denke also an eine andere Klasse in meinem Modell, die ein INoteRepository enthält.

%Vor%

Das würde natürlich funktionieren, aber ich frage mich, ob das die richtige Architektur ist? Ich kuppel die einfache DTOClass zu einer anderen Data Access-Klasse und möglicherweise auch zu meinem DI-Mechanismus (wie ich eine Instanz der Data Access-Klasse im Getter von Notes erstellen muss).

Würdest du es anders machen? Gibt es einen besseren Weg dies zu tun, auch wenn ich bedenke, dass ich Ninject bereits verwende?

Ich vermute, dass dies kein POCO oder DTO mehr ist, da es jetzt Logik enthält, aber das ist in Ordnung. Ich möchte, dass es wie ein POCO für externe Aufrufer erscheint , so dass ich lieber eine Eigenschaft "Notizen" als Methoden wie "GetNotesForProject" für diese oder andere Klassen habe.

Meine aktuelle Lösung ist wirklich hässlich, da ich den Ninject-Kernel von meiner MvcApplication holen muss, um die ProjectDataProvider-Klasse hochzufahren, die ein INoteRepository in ihrem Konstruktor verwendet, um das INoteRepository irgendwo in meinem "DTO" zu platzieren "-Klasse:

%Vor%

Bearbeiten: Eröffnete ein Kopfgeld. Lassen Sie uns die Terminologie von "POCO" und "DTO" ignorieren, ich werde entsprechend umgestalten. Es geht also darum: Wie sollte der Lazy-Loading-Code in solch einer Situation aussehen, und kann / sollte ich es vermeiden, INoteRepository in die MyDTOClass zu geben?

    
Michael Stum 28.12.2009, 13:37
quelle

7 Antworten

8

Ihr DTO muss nicht über das Repository selbst Bescheid wissen. Alles was es braucht, ist ein Delegat, der ihm den Wert für Notizen zur Verfügung stellen kann.

Wie wäre es mit so etwas:

%Vor%

Da Ihr Repository definitionsgemäß eine Instanz des DTO bereitstellen soll, sollten wir den value provider delegate wie folgt übergeben können:

%Vor%

Funktioniert das für Sie?

    
madaboutcode 12.01.2010, 16:23
quelle
7

Wenn Sie auf .Net 4 warten können (dh Ihre noch nicht in Produktion) Lazy (of T) ist eine neue Lazy Loading Funktion im .Net Framework. Ссылка

    
dtoland 28.12.2009 13:54
quelle
2

Sie vereiteln den ganzen Zweck von DTOs, wenn Sie versuchen, Lazy-Loading-Logik hinzuzufügen. Ich denke, Sie sollten zwei getrennte Objekte haben: eins mit Note s und ein anderes - ohne sie.

    
Anton Gogolev 28.12.2009 13:38
quelle
2

Eine weitere Option besteht darin, Proxies zu verwenden, die von den Objekten erben, die Sie abrufen möchten (entsprechend der Führung einiger objektrelationaler Mapper wie NHibernate).

Dies bietet eine gewisse Ignoranz bei der Persistenz, indem der Datenzugriffscode vom Domänenmodell getrennt ist:

%Vor%

MyDTOClassRepository deklariert das Basisobjekt als Rückgabetyp, gibt aber stattdessen das träge Objekt zurück:

%Vor%

MyDTOClass Konsumenten müssen nicht wissen, dass sie mit Proxies zu tun haben, noch müssen sie mit Repositories interagieren (außer für welche Klasse auch immer der erste Aufruf erfolgt).

    
Jeff Sternal 12.01.2010 16:42
quelle
1

Nachdem ich die astralen Reiche für Äonen in verzweifelter Suche nach einer Antwort durchstreift habe, bin ich zu der endgültigen Schlussfolgerung gelangt, dass es unnötig ist, ein Repository in Ihre Entitätsinstanz zu überführen, da ein Repository für einen Entitätstyp immer ein Singleton.

Sie könnten also in Ihrer Entitätsklasse einfach so schreiben:

%Vor%

Das hat wirklich alle Kopfschmerzen für mich gelöst.

Das Repository muss so implementiert werden, dass es immer weiß, was mit den Daten geschehen soll.

Denken Sie daran, dass eine Repositoryimplementierung beispielsweise die Daten von der Datenbank abrufen würde, während eine andere sie von einem Webdienst erhalten könnte. Aufgrund der losen Kopplung ist das Repository-Implementierungsmodul leicht ersetzbar und jede Datenkommunikation ist sogar beliebig verkettbar.

Wenn Sie ein Szenario haben, in dem Sie sagen würden, "aber das Repository kann nicht singleton sein, weil ich ein komplexes Szenario habe, in dem ich zum Beispiel auf mehr als eine Datenquelle zugreife und es von der tatsächlichen Monster Instanz abhängt, wo es hinkommt Die Victim s von ", dann sage ich gut, Sie müssen eine Repository-Implementierung erstellen, die alle Datenquellen kennt und verfolgt, woher die Entity-Instanzen kommen und wohin sie gehen, und so weiter ...

Wenn Sie der Meinung sind, dass dieser Ansatz nicht genug POCO ist, müssen Sie eine weitere lose gekoppelte Business Logic-Schicht erstellen, die die POCO-Entität umschließt oder ableitet und die Repository-Interaktion dort implementiert.

Ich hoffe, ich könnte einen Hinweis geben in eine Richtung, die sich für Sie und für jeden richtig anfühlt. Ich glaube tatsächlich, dass dies der heilige Gral für die Multilayer / -tier-Entwicklung ist. Fühlen Sie sich frei, weiter zu diskutieren.

    
herzmeister 09.01.2010 01:58
quelle
1

Sie können keine Unabhängigkeit von Ihrem Repository erreichen, wenn Sie es von dort laden. Sie können es auf Distanz halten, indem Sie einen Callback oder Proxy verwenden oder NHibernate die Drecksarbeit für Sie erledigen lassen, aber Ihr DTO muss auf das Repository zugreifen, um die Notes zu laden.

Ihr Hauptziel scheint zu sein: "Ich möchte, dass es wie ein POCO für externe Anrufer erscheint, daher möchte ich lieber eine Eigenschaft" Notizen "als Methoden wie" GetNotesForProject "für diese oder andere Klassen haben." Kannst du das nicht mit Ninject und Konstruktorinjektion erreichen? Sobald Sie ninject eingerichtet haben, können Sie kernel.Get () aufrufen, um eine neue Instanz zu erhalten, die keinen Verweis auf Ihr Repository enthält.

    
Jamie Ide 12.01.2010 17:19
quelle
0

Sie könnten die Notes-Eigenschaft in einem INoteRepository als Parameter verwenden lassen. Auf diese Weise könnte der aufrufende Code in der richtigen Instanz von INoteRepository übergeben werden.

    
Kevin Pang 08.01.2010 23:21
quelle

Tags und Links