Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi [ORM] Lazy Loading - Wie implementieren? (https://www.delphipraxis.net/163286-%5Borm%5D-lazy-loading-wie-implementieren.html)

mquadrat 23. Sep 2011 10:56

[ORM] Lazy Loading - Wie implementieren?
 
Hallo zusammen,

Ich hab mal wieder was aus der Ecke der Konzepte. Wie würdet ihr in einem ORM in Delphi Lazy Loading implementieren? Das Mapping des OR soll komplett extern erfolgen, also z.B. über XML-Konfigurationsdateien oder Attribute. Es sollen keine Getter / Setter von Hand geschrieben werden. Direkter Zugriff auf Relationen soll über Properties möglich sein (also z.B. Rechnung.Kunde.Adresse, wobei Adresse als lazy loading in Kunde gekennzeichnet wäre).

Generell gibt es für Lazy Loading ja vier Möglichkeiten:

- Lazy Initialization: Die Property wird null-initialisiert. Beim ersten Zugriff wird das passende Objekt erstellt und geladen.
- Virtual Proxy: Es wird ein Objekt erstellt, dass das gleiche Interface wie die Zielklasse hat. Alle Aufrufe werden durchgeroutet.
- Virtual Holder: Statt das Objekt direkt aufzurufen wird immer die getValue() Funktion des Holders aufgerufen.
- Ghost: Das korrekte Objekt wird erstellt, aber nicht befüllt.


Lazy Initialization
Hierfür müsste entweder der Getter von Hand geschrieben werden oder "self-aware" Properties verwendet werden. Ich habe es noch nicht ausprobiert, aber ich denke dass müsste sich mit den Properties aus DSharp (oder einem ähnlichen Konzept) realisieren lassen.

Virtual Proxy
Um Code-Generierung zu vermeiden, müsste das Interface zur Runtime aufgebaut werden. Selbst wenn das geht, würde ich allerdings aufgrund der Typsicherheit von Delphi Probleme bei der weiteren Geschäftslogik erwarten oder es müsste im weiteren Verlauf immer eine Methode "getRealObject" mit dem richtigen Typ geben. Nicht wirklich komfortabel und schon fast ein Virtual Holder.

Virtual Holder
Sollte sich mit Generics durchaus machen lassen, sagt mir aber vom Konzept her so gar nicht zu.

Ghost:
Hier mat man ein ähnliches Problem wie bei der Lazy Initialization. Die Properties müssen den Zugriff realisieren und ggf. das Laden der Daten triggern. Man hat das Problem also von der aufrufenden Klasse in die aufgerufene Klasse verschoben. Auch das müsste mit den Properties von DSharp gehen, die Ihren Owner kennen.


Fazit:
Proxy und Holder haben IMHO konzeptionelle Unschönheiten, erlauben allerdings das Verwenden von "Standard-Properties". Lazy Initialization und Ghost verlangen den Einsatz von intelligenten Properties, was etwas unhandlich aber machbar ist. Ich würde also zu einem der beiden letzten tendieren.



Welche anderen Implementierungsmöglichkeiten gibt es? Was habe ich übersehen? Wie arbeiten existierende Delphi ORMs?

Namenloser 23. Sep 2011 12:39

AW: [ORM] Lazy Loading - Wie implementieren?
 
Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes
Delphi-Quellcode:
if not Assigned(Field) then Field := ...
im Getter ist nun wirklich nicht die Welt...

r2c2 23. Sep 2011 15:12

AW: [ORM] Lazy Loading - Wie implementieren?
 
Das ist ein sehr interessantes Problem. Hab ich mir noch gar keine Gedanken dazu gemacht.

Zitat:

Zitat von mquadrat (Beitrag 1126168)
Welche anderen Implementierungsmöglichkeiten gibt es?

Weitere sind mir nicht bekannt.

Zitat:

Wie arbeiten existierende Delphi ORMs?
Kann ich dir leider nicht sagen. Ist aber nachguckbar.

Zitat:

Zitat von NamenLozer (Beitrag 1126198)
Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes
Delphi-Quellcode:
if not Assigned(Field) then Field := ...
im Getter ist nun wirklich nicht die Welt...

Es geht darum, dass Persistenz im Idealfall orthogonal zur Geschäftslogik sein sollte. Klar ist es nicht viel "Arbeit", aber unsauber. Wenn man den Mechanismus ändern will, kriegt man Probleme, der zusätzliche Code ist ne zusätzliche Fehlerquelle (lustig, wenn man sowas mal vergisst) und es macht den Code unübersichtlicher. Das ist jetzt nichts, was jetzt katastrophale Auswirkungen hätte. Es ist nur unschön und kann zu vermeidbaren Problemen führen. Und genau deshalb halte ich es für sinnvoll, hier zwei, drei Gedanken mehr drauf zu verschwenden.


Zwei Gedanken deshalb von mir:
- LazyInitialization könnte man u.U. mit Annotationen/Attributen reparieren. Also den Lazy-Initialization-Code zur Laufzeit einfügen. Hab ich aber nich nie gemacht, kann dazu also leider nicht viel sagen.
- Den Proxy fände ich eigentlich auch am schönsten, weil nun wirklich orthogonal. Ob man zu Laufzeit den Proxy erzeugen kann, weiß ich nicht. In Java geht das und so hege ich die Hoffnung, dass es in Delphi auch ne Möglichkeit gibt. Probleme mit der Typisierung sehe ich da nicht. Es könnte nur sein, dass das zur Laufzeit nicht geht und man auf Code-Generatoren ausweichen muss.

mfg

Christian

mquadrat 23. Sep 2011 15:58

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von r2c2 (Beitrag 1126245)
Das ist ein sehr interessantes Problem. Hab ich mir noch gar keine Gedanken dazu gemacht.

Da immer bedauert wurde, dass in Delphi-Land so wenig über Konzepte nachgedacht wird, wollte ich das mal anstoßen :D

Zitat:

Zwei Gedanken deshalb von mir:
- LazyInitialization könnte man u.U. mit Annotationen/Attributen reparieren. Also den Lazy-Initialization-Code zur Laufzeit einfügen. Hab ich aber nich nie gemacht, kann dazu also leider nicht viel sagen.
- Den Proxy fände ich eigentlich auch am schönsten, weil nun wirklich orthogonal. Ob man zu Laufzeit den Proxy erzeugen kann, weiß ich nicht. In Java geht das und so hege ich die Hoffnung, dass es in Delphi auch ne Möglichkeit gibt. Probleme mit der Typisierung sehe ich da nicht. Es könnte nur sein, dass das zur Laufzeit nicht geht und man auf Code-Generatoren ausweichen muss.
Hätte beim Proxy die Property nicht den Typ des Proxys statt der eigentlichen Klasse? Oder möchtest du die eigentliche Klasse verstecken und immer den Proxy verwenden? Könnte aber auch sein, dass ich gerade auf der Leitung stehe, nachdem ich mich über die Live-Bindings Doku geärgert habe :oops:

r2c2 23. Sep 2011 16:10

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von mquadrat (Beitrag 1126266)
Hätte beim Proxy die Property nicht den Typ des Proxys statt der eigentlichen Klasse?

Nö.

Zitat:

Oder möchtest du die eigentliche Klasse verstecken und immer den Proxy verwenden?
Nö.

Bei nem Proxy hast du immer ne Basisklasse (bzw. ein Interface). Siehe GoF:207 oder, falls du das GoF-Book nicht zu Hand haben solltest, zur Not auch Wikipedia. Du deklarierst immer den Supertyp, hast aber entweder die eigentliche Klasse oder eben den Proxy. Der Code, der das nun verwendet, kriegt den Unterschied gar nicht mit ==> abstrakte Kopplung.

Zitat:

Könnte aber auch sein, dass ich gerade auf der Leitung stehe, nachdem ich mich über die Live-Bindings Doku geärgert habe :oops:
Hab die nicht gesehen. Was ärgert dich daran?

mfg

Christian

mquadrat 23. Sep 2011 16:19

AW: [ORM] Lazy Loading - Wie implementieren?
 
:wall: Interface.. logisch..


EDIT: Was mich an der Live-Binding Doku ärgert? Sie ist praktisch nicht existent :-)

Namenloser 23. Sep 2011 16:27

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von r2c2 (Beitrag 1126245)
Zitat:

Zitat von NamenLozer (Beitrag 1126198)
Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes
Delphi-Quellcode:
if not Assigned(Field) then Field := ...
im Getter ist nun wirklich nicht die Welt...

Es geht darum, dass Persistenz im Idealfall orthogonal zur Geschäftslogik sein sollte. Klar ist es nicht viel "Arbeit", aber unsauber. Wenn man den Mechanismus ändern will, kriegt man Probleme, der zusätzliche Code ist ne zusätzliche Fehlerquelle (lustig, wenn man sowas mal vergisst) und es macht den Code unübersichtlicher. D

1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?
2. Normal lässt man bei ORMs den Code doch eh generieren, da kann man doch den Getter ohne Probleme einbauen.
3. Was ist daran unsauber?

Meflin 23. Sep 2011 16:32

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von mquadrat (Beitrag 1126271)
:wall: Interface.. logisch..

Ich weiß nicht was mit Delphi möglich ist, NHibernate, mit dem ich gerade arbeite, implementiert die Proxies als zur Laufzeit erzeugte Ableitung der Entity.

Ach und weil du Konfiguration über XML erwähnt hast: Wer will das machen?? Automapping FTW, nur so als Denkanstoß :cyclops:

mquadrat 23. Sep 2011 16:41

AW: [ORM] Lazy Loading - Wie implementieren?
 
@NamenLozer

Besser ist es IMHO, wenn der ORM keinen Code vorgenerieren muss, bzw. ich beliebige Klassen persistieren kann, von denen der ORM vorher noch gar nichts wusste.


@Meflin

Gute Frage. Mit dem Thema Code dynamisch zur Lautzeit erstellen habe ich mich bislang noch nicht befasst gehabt.

Automapping? Das funktioniert aber doch nur wenn
  • die Spaltennamen identisch oder zumindest ableitbar sind (Bei SAP sind z.B. alle Spaltennamen 5-stellig.. nicht wirklich sprechende Namen)
  • die Datentypen identisch oder ableitbar sind (Was ist wenn die Geschäftslogik mehr Typen kennt als die DB, also kein 1:1 Mapping möglich ist?)
  • keine weiteren Metadaten verwendet werden sollen (Ich würde das - auch wenn man sich drüber streiten kann in welcher Ebene validiert werden soll - mit Validierungsinfos anreichern).


EDIT: Ich würde das Mapping sowieso abstrahieren. Ob das dann aus einer XML, aus Attributen oder aus einem Automapping kommt kann sich ja dann jeder aussuchen :D

Meflin 23. Sep 2011 16:59

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von mquadrat (Beitrag 1126277)
Automapping? Das funktioniert aber doch nur wenn...

OK, ich ging davon aus, man baut ein neues System. Anders sieht es vielleicht aus, wenn die Datenbank samt Daten schon existiert und ein neuer Client dafür entwickelt werden soll. Hier muss man vielleicht mehr manuell konfigurieren. In ersterem Fall will ich ja aber eigentlich nur die Ausnahmen der Regel konfigurieren, und nicht prinzipiell jedes einzelne Mapping. Das Mapping austauschbar zu machen ist daher ein sehr begrüßenswerter Schritt :thumb:

Zum Thema Automapping: Ich finde das sehr elegant, wie Fluent NHIbernate das löst. Einerseits gibt es hier Conventions, die man einfach als Klasse implementieren kann (z.B. kann man darüber Tabellen/Spalten/Fremdschlüsselnamen etc generieren). Andererseits kann man glaube ich zumindest einzelne properties trotzdem manuell überschreiben (auch wenn ich das noch nie gemacht habe).

NHibernate an sich zu verwenden kam für uns jedenfalls aufgrund des XML-Overheads absolut nicht in Frage, deshalb dann Fluent NHibernate, welches ich dir als Anregungsimplementation größtenteils sehr empfehlen kann ;)

mquadrat 23. Sep 2011 17:04

AW: [ORM] Lazy Loading - Wie implementieren?
 
Mal schauen, vielleicht wird ja aus dem "In-House-Projekt" mal ein ausgewachsener ORM. Aktuell evaluiere ich ja eh erst mal, ob ich was passendes finde oder eben selber was schreiben muss. Das Lazy Loading hat mich jetzt vor allem mal konzeptionell interessiert.

r2c2 23. Sep 2011 17:04

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von NamenLozer (Beitrag 1126275)
1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?

Normalerweise sollte eine Klasse nur eine Aufgabe haben (Single Responsibility Principle) oder anders ausgedrückt: verschiedene Aufgaben sollten auch verschiedene Klassen aufgeteilt werden (Separation Of Concerns). Das sind grundlegende Prinzipien der Softwareentwicklung, die helfen Software wartbar zu machen. Man kann so leicht Teile austauschen, ändern und wiederverwenden ohne dabei unnötigen Aufwand zu haben und unnötig Fehler zu produzieren.

So sollte also die Persistenz (das Speichern in der DB) unabhängig von der eigentlichen Programmlogik sein (das nennt man Orthogonalität). im Idealfall steht in den Klassen die gespeichert werden sollen gar kein Code, der sich ums Speichern kümmert. Das Speichern steht in einer anderen Klasse, die jedes beliebige Objekt speichern kann.

Nicht immer ist Orthogonalität einfach zu erreichen, aber es hat ja auch niemand behauptet Softwareentwicklung wär immer nur einfach.

Zitat:

2. Normal lässt man bei ORMs den Code doch eh generieren, da kann man doch den Getter ohne Probleme einbauen.
Wenn man drum herum kommen kann, verzichtet man lieber aufs generieren. Es ist ein zusätzlicher Schritt, der den build-Prozess verkompliziert und damit fehleranfällig macht. Manchmal ist das Generieren von Code aber der schlauere Weg, weil man dadurch ganz andere Fehlerquellen vermeidet. Es ist eben eine Abwägungssache.

Zitat:

3. Was ist daran unsauber?
Die fehlende Orthogonalität.

Zitat:

Zitat von Meflin (Beitrag 1126276)
[
Ich weiß nicht was mit Delphi möglich ist, NHibernate, mit dem ich gerade arbeite, implementiert die Proxies als zur Laufzeit erzeugte Ableitung der Entity.

Das ist das, was ich meine. In Java gibt es eine proxy-Klasse, die zur Laufzeit beliebige Interfaces implementieren kann. Die wird u.a. für RMI verwendet um die Stubs/Proxys zu erzeugen und ich vermute mal Hibernate benutzt das auch.


mfg

Christian

Namenloser 23. Sep 2011 17:22

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von r2c2 (Beitrag 1126283)
Zitat:

Zitat von NamenLozer (Beitrag 1126275)
1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?

Normalerweise sollte eine Klasse nur eine Aufgabe haben (Single Responsibility Principle) oder anders ausgedrückt: verschiedene Aufgaben sollten auch verschiedene Klassen aufgeteilt werden (Separation Of Concerns). Das sind grundlegende Prinzipien der Softwareentwicklung, die helfen Software wartbar zu machen. Man kann so leicht Teile austauschen, ändern und wiederverwenden ohne dabei unnötigen Aufwand zu haben und unnötig Fehler zu produzieren.

Jo, weiß ich, mach ich natürlich auch so. Sehe aber nicht inwiefern der Getter dieses Prinzip verletzt. Der Getter erzeugt ja nur das Objekt mit dem entsprechenden Parameter (z.B. ID), das eigentliche Laden sollte dann das erzeugte Objekt anstoßen – der Code zum Laden selbst sollte natürlich wieder in eine weitere Klasse ausgelagert sein. Diese Klasse (die ein festgelegtes Interface implementiert) könnte man entweder als Parameter im Konstruktor übergeben, oder sonstwie registrieren, wodurch sich der Ladecode nachträglich austauschen lässt.

In der Datenklasse steht dann kein Code, der sich direkt um die Persistenz kümmert, lediglich ein Getter, der eine Eigenschaft zurückliefert. Das würde ich noch nicht als Geschäftslogik bezeichnen.

mquadrat 23. Sep 2011 17:36

AW: [ORM] Lazy Loading - Wie implementieren?
 
Lazy Initialization widerspricht dem meiner Meinung nach auch nicht. Der Punkt ist viel mehr, dass es viel bequemer ist, wenn das der ORM übernehmen kann :-) Wenn die Anwendung nichts von der DB wissen soll, dann weiß sie auch nicht wie teuer es ist ein bestimmtes Objekt zu erzeugen. Hier kann man dann ggf. beim Mapping eingreifen, womit das Lazy Loading in das Hoheitsgebiet des ORM fällt.

Elvis 23. Sep 2011 20:27

AW: [ORM] Lazy Loading - Wie implementieren?
 
Proxies von Interfaces scheinen mir hier am sinnvollsten zu sein.

Mir fallen da spontan ein paar Wege ein:
  • TVirtualInterface
    In XE2 kam die Klasse TVirtualInterface hinzu. Die sollte dir schonmal einen Ansatz geben, um zur Laufzeit eine Implementierung eines Interfaces zu erzeugen.
    Was in Delphi halt immer noch komplett bescheuert (höflich ausgedrückt) ist, ist, dass man immer noch ewig viel hässlichen Code tippen muss, nur um eine dumme Property in ein Interface zu kriegen.
    Du musst also immer noch komplett hirnlose Getter/Setter schreiben und die Property selbst auch noch.
    Gibt aber schlimmeres denke ich mal.
    Collection-Properties würdest du initialisieren, da bräuchte man dann nur einen Getter,
    Als zugrundeliegenden Store für die Properties könntest du ein Dictionary und TValue nehmen.
  • Maschinencode zur Laufzeit erzeugen
    Wenn du die TVirtualInterface-Lösung am Laufen hast, kannst du ja versuchen tatsächliche Klassen zur Laufzeit zu erzeugen.
    Aber ohne IL/Byte-Code ist das gleich mal 100-mal aufwendiger und instabiler. In IL gibt es eine Exception, wenn der IL Code nicht verifiziert, in native Delphi schreibst du fröhlich irgendwas irgendwohin und 10 Minuten später knallt es an einer ganz anderen Stelle.
    Nur mit so einem Runtime-Codegen könntest du auch dynamisch Proxies für Klassen erzeugen.
  • Automatisch erzeugte Proxies zur Compilezeit
    Ein einfacherer Weg wäre es wohl, wenn du es zur Pflicht machst, dass dein Modell in einem Package liegt.
    Dann könntest du dieses im Post-Build laden, die Typen finden und nun relativ einfach die Proxies als Delphi Code erzeugen.
    Die fertige App muss ja deshalb noch lange keine Runtime-Packages benötigen, wäre also keine so schlimme Einschränkung.
    Der erzeugte Code müsste dann nur irgendwo so registriert werden, dass dein ORM weiß, wie er zur Laufzeit die Proxies finden kann.
    Das hier würde es auch ermöglichen, Klassen anstatt Interfaces für das Modell nehmen zu können.
    Denn zirkuläre Bezüge bringen das autom. Referenzzählen immer durcheinander, und ein Modell ohne die Möglichkeit den Graph hoch & runter zu navigieren ist bekanntlich grauenvoll. ;-)

btw: Ich weiß nicht wieweit tiOpf ist. In meinen alten Delphi-Tagen fand ich es immer ein wenig zu einschränkend und creepy. Aber das muss ja gar nicht mehr so sein.
Damit hättest du das Thema ORM/OPF abgehakt.

mjustin 25. Sep 2011 08:52

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von Meflin (Beitrag 1126279)
NHibernate an sich zu verwenden kam für uns jedenfalls aufgrund des XML-Overheads absolut nicht in Frage, deshalb dann Fluent NHibernate, welches ich dir als Anregungsimplementation größtenteils sehr empfehlen kann ;)

Den XML "Overhead" kann man aber nach meiner Erfahrung zumindest in den Java Hibernate Versionen gut nutzen, um aus den HBM (Hibernate Mapping) Dateien, die man sich entweder automatisch per Hibernate Tool aus den Datenbankmetadaten erzeugt oder manuell erstellt, automatisch Delphi Quelltext für die Datenklassen zu erzeugen.

Unter http://hbm2pascal.appspot.com/ habe ich eine Online-Anwendung dafür, der Delphicode wird dynamisch aus den HBM Daten erzeugt. Wenn es für Delphi einmal gutes Templatig System geben sollte, lässt es sich das hbm2pascal Tool auch komplett in Delphi bauen.

Haken ist allerdings, dass XML für die Definition der Tabellen / Felder / Referentiellen Integritäten verwendet wird. Doch wenn man DB-Werkzeuge wie IBExpert & Co. hat, lässt sich über deren Editor ja auch bequem arbeiten und anschliessend läßt man DDL2HBM drüber laufen.

neo4a 25. Sep 2011 11:17

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von Meflin (Beitrag 1126279)
dann Fluent NHibernate, welches ich dir als Anregungsimplementation größtenteils sehr empfehlen kann ;)

In der Delphi-Praxis sind Konzepte aus der Java-Welt viel zu oft nur
Delphi-Quellcode:
virtual;abstract;
;) Selbst wenn die Konzepte überzeugen, wird eine Implentierung leider häufig auch durch die speziellen Delphi-Gegebenheiten beschränkt.

Soweit ich das beurteilen kann, findet sich bei unseren französischen Kollegen eine funktionierende Delphi-Implementierung dieses Fluent- NHibernate- ORM- Ansatzes. Der "spiritus rector" hat für meinen Geschmack ein wenig zu lange für das französische Militär gearbeitet: Wenn man den Formalismus aus seiner 600-Seiten Dok. entfernt, bleiben ca. 50 Seiten Substanz, die dann aber sehr interessant sind.

Nicht nur dasLazy Loading verlangt von dem Entwickler ein hohes Maß an Vertrauen (die Quelle spricht u.a. von Pest und Cholera) in das Framework und seine Leistungsfähigkeit. Die zugrunde liegende Implementierung erscheint mir jedenfalls immer sehr komplex und durch Formalismen aufgebläht, so dass mir in der täglichen Praxis der direkte Weg irgendwie "sicherer" erscheint (und ich mich trotzdem damit nicht wohler fühle).

mquadrat 26. Sep 2011 09:01

AW: [ORM] Lazy Loading - Wie implementieren?
 
Ist ja doch noch eine muntere Diskussion geworden ;)

Ich werde bei Gelegenheit mal einige der existierenden ORMs anschauen.

generic 26. Sep 2011 09:51

AW: [ORM] Lazy Loading - Wie implementieren?
 
In Delphi XE wurde der TVirtualMethodInterceptor eingeführt.
Da drüber würde sich auch sehr einfach was basteln lassen.

Stevie 26. Sep 2011 09:58

AW: [ORM] Lazy Loading - Wie implementieren?
 
Sehr interessanter Thread.

Ich denke, man muss hier unterscheiden zwischen 1 zu 1 Relationen und 1 zu n Relationen. Lazy loading für 1 zu n Relationen sind imo einfacher zu implementieren, da man hier die Logik in die Listenklasse implementieren kann. Hierbei muss man dann auch darauf achten, ob man pro Listen Element ein SQL abfeuert (z.B. bei Linq to SQL Standard verhalten) oder ob man beim Zugriff auf die Liste diese direkt komplett befüllt (gibts afair auch eine Einstellung bei Linq to SQL).

In einem DSharp Prototypen benutze ich eine von TObjectList<T> abgeleitete Klasse, um das zu realisieren.

Lazy loading für 1 zu 1 Relationen zu implementieren, halte ich mit derzeitigem Stand für etwas schwieriger. Möglicherweise könnte man an dieser Stelle mit einem virtuellen Getter arbeiten, welcher über TVirtualMethodInterceptor zur Laufzeit erweitert wird.

Ich muss mich mit der gesamten ORM Thematik nochmals auseinander setzen - eventuell bietet sich dort auch meine jüngste AOP Implementierung an.

mquadrat 26. Sep 2011 10:15

AW: [ORM] Lazy Loading - Wie implementieren?
 
Ein virtueller Getter mit Interceptor würde sicher funktionieren. Das blöde dabei ist nur, dass man wenig Nutzen hat. Man muss trotzdem einen Getter implementieren, damit etwas zum intercepten da ist. In diesem Fall würde man also ca. drei Zeilen handgeschriebenen Code (manuelle Lazy Initialization) durch eine Zeile handgeschrieben Code + Attribut + Interception + Rtti + ORM Code ersetzen. Nicht wirklich schlank ;)

Kann aber auch daran liegen, dass ich bis jetzt erst einen Kaffee getrunken habe :D

Stevie 26. Sep 2011 10:21

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von mquadrat (Beitrag 1126646)
drei Zeilen handgeschriebenen Code (manuelle Lazy Initialization)

Wie soll diese manuelle lazy initialization ohne dependency denn realisiert werden?

mquadrat 26. Sep 2011 10:27

AW: [ORM] Lazy Loading - Wie implementieren?
 
Ohne Dependency auf den ORM natürlich gar nicht ;) Den müsste man injecten.

Stevie 26. Sep 2011 10:47

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von mquadrat (Beitrag 1126650)
Ohne Dependency auf den ORM natürlich gar nicht ;) Den müsste man injecten.

Genau das gilt es zu verhindern. Denn eine Abhängigkeit auf den ORM in nem PODO ist imo ein no go.

Elvis 26. Sep 2011 11:13

AW: [ORM] Lazy Loading - Wie implementieren?
 
Lazy ist auch unbedingt auf dein einelnen Entitäten nötig.
Denn wenn du einen Customer über den key liest, ihm eine weitere Addresse zuordnest und abspeicherst, müsste der Customer-Datensatz in der Tabelle nie angefasst werden. (so mach das (n)Hibernate zum Bleistift)
Das Implemtieren von Getter/Setter könnte auch durch abstrakte GetteR/Setter reduziert werden, dann müsste der Interceptor halt einen eigenen Store nutzen (e.g. ein Dictionary)
Aber vllt solltet ihr einfach Bolemb mit Liebesentzug drohen, wenn die nicht schleunigst virtuelle und vor allem abstrakte Properties erlauben, ohne explizit Setter angeben zu müssen. (Ähnlich zu Oxygene)

Das Problem, das ich bei den TVirtualInterface oder MethodInterceptor sehe ist, dass da sehr sehr viele Indirektionen im Spiel sind. Das kann schnell ganz schön lahm werden.

Mal schauen wie Embello das löst, also ob die auch weitere Felder für die Proxies zulassen, so dass man nicht auch noch durch ein Dictionary müsste. Ganz zu schweigen von tatsächlich überschrieben Methoden, nicht nur Interceptions. Wenn man für jeden Call erstmal nachkieken muss, was wirklich ausgeführt werden muss, dann tut das doch weh. :cry:

Stevie 26. Sep 2011 11:49

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von Elvis (Beitrag 1126660)
Mal schauen wie Embello das löst, also ob die auch weitere Felder für die Proxies zulassen, so dass man nicht auch noch durch ein Dictionary müsste. Ganz zu schweigen von tatsächlich überschrieben Methoden, nicht nur Interceptions. Wenn man für jeden Call erstmal nachkieken muss, was wirklich ausgeführt werden muss, dann tut das doch weh. :cry:

Wird Emballo noch aktiv weiterentwickelt? Oder ist das Repo auf google code nicht das aktuelle?

Elvis 26. Sep 2011 12:24

AW: [ORM] Lazy Loading - Wie implementieren?
 
Zitat:

Zitat von Stevie (Beitrag 1126671)
Wird Emballo noch aktiv weiterentwickelt? Oder ist das Repo auf google code nicht das aktuelle?

Der Code liegt auf Bitbucket. https://bitbucket.org/magnomp/emballo

Stevie 26. Sep 2011 12:48

AW: [ORM] Lazy Loading - Wie implementieren?
 
Mit DSharp kann man sowas machen. (virtueller Getter mit RTTI vorausgesetzt)

mquadrat 26. Sep 2011 13:29

AW: [ORM] Lazy Loading - Wie implementieren?
 
Ich schätze mal, ich werd die verschiedenen Möglichkeiten einfach mal ausprobieren müssen. Für in-depth Test hab ich allerdings aktuell wenig Zeit. Messe steht an..


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz