![]() |
Delphi-Version: XE5
Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Ich und Datenbanken.
Ich möchte auf die Schnelle eine ganz Methode schaffen, eine bestimmte Klasse in eine DB zu persistieren und aus einem bestimmten Datensatz einer DB wieder eine Instanz rekonstruieren zu können. Hierbei frage ich mich, als absoluter Idiot in Sachen "DBs mit Delphi": Wie schreibe ich am besten in eine Datenbank? Bislang habe ich immer eine Query gehabt, die irgendwie zusammengebastelt und (evtl. als Bestandteil einer Transaktion) abgeschickt. Wenn ich Daten haben wollte, dann auch wieder mit Queries abgeholt. Jetzt sehe ich beispielsweise noch
Delphi-Quellcode:
. Oder auch nur
TDataSet.AppendRecord(const Values: array of const)
Delphi-Quellcode:
, anschließend in alle möglichen
TDataSet.Append()
Delphi-Quellcode:
-Objekte etwas zu schreiben und es mit einem
TField
Delphi-Quellcode:
abzuschließen.
TDataSet.Post()
So wie es für mich auf die Schnelle aussieht, kann ich auf einem TDataSet immer auf das zugreifen, wo grade der Cursor steht. Gibt es irgendwie eine gängige Klasse welche eine "Table Row" kapselt? Ich hätte meiner zu serialisierenden Klasse spontan gerne einfach eine Methode verpasst mit der man einfach hätte sagen können
Delphi-Quellcode:
.
mySQLTable.AppendRow(meinObjekt.toTableRow())
|
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Das wäre dann wohl
Delphi-Quellcode:
, dort findest du alle Felder des aktuellen Datensatzes.
TDataset.Fields
|
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Da kommt schon etwas mehr auf dich zu, als nur ein paar Feldinhalte eines Datasets zu beschreiben. Dazu müsstest du ja erst mal festlegen, welche Eigenschaften deines Objekts wie in welchen Felder der Datenbank gespeichert werden. Für das Lesen gilt selbiges, wobei man da noch klären sollte, wie mit NULL-Werten der Datenbank verfahren werden soll.
Nächstes Problem: wie weiß deine Instanz denn, ob nicht schon ein entsprechender Datensatz in der Datenbank existiert, respektive wie findest du die Datensätze wieder? Wenn du es mal ausprobieren willst, lad dir doch die Demo von TMS Aurelius runter. Da ist das schon sehr detailliert implementiert und im Gegensatz zu manch anderem ORM-System muss man die Klassen auch nicht von einem speziellen Vorfahren ableiten. |
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Klar, ein vernünftiges ORM zaubert man sich wirklich nicht in einer Viertelstunde aus dem Hut. :wink:
Ich wollte jetzt wirklich keinen Hibernate-Klon erschaffen, sondern einer einfachen Klasse eher für Debug-Zwecke eine Art
Delphi-Quellcode:
und
myObject.toXML(): TStringStream
Delphi-Quellcode:
verpassen die dann von einem entsprechenden Persistierer (was für ein Wort :roteyes:)entgegengenommen und gespeichert werden können.
myObject.toDB(): TFields
Probleme mit NULL-Werten oder Prüfen auf Gleichheit sehe ich weniger. Ersteres hätte ich über DB-Constraints geregelt, zweites erst auf Objekt-Ebene, also nach der Deserialisierung. Da ich (zum Glück) nie allzu viel Zeit mit J2EE-Entwicklung verbracht habe, hänge ich bei so etwas natürlich schon wieder an Grundsatzfragen ("Sollte die Klasse selbst sich überhaupt mit ihrem Ziel-Serialisierungsformat herumplagen müssen?"), aber das packe ich wohl besser in ein eigenes, allgemeineres Thema :) |
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Es gibt verschiedene prinzipielle Ansätze:
|
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Das Visitor Pattern habe ich mir nie genauer angesehen, in freier Wildbahn ist es mir bislang nie über den Weg gelaufen. Ich habe heute Abend zumindest angefangen, es mir genauer anzuschauen, und von allen Artikeln ist
![]() Nach den ersten zwei von vier Teilen habe ich wohl den Grundgedanken verstanden: Das ist so ziemlich genau das, was ich wollte. :cheers: |
AW: Gibt es ein Objekt das eine "Zeile" einer DB kapselt?
Der Visitor von Uwe hat ein paar Beschränkungen hinsichtlich der Generics (z.B.
Delphi-Quellcode:
) oder bei gleichlautenden Klassennamen aus unterschiedlichen Units.
TList<T>
Hier meine Visitor-Interpretation
Delphi-Quellcode:
unit View.Main;
interface uses Visitor, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMainView = class( TForm ) Button1 : TButton; Edit1 : TEdit; Label1 : TLabel; Memo1 : TMemo; procedure Button1Click( Sender : TObject ); private procedure PrepareVisitor( AVisitor : TVisitor ); public end; var MainView : TMainView; implementation {$R *.dfm} procedure TMainView.Button1Click( Sender : TObject ); var LVisitor : TVisitor; LIdx : Integer; begin LVisitor := TVisitor.Create; try PrepareVisitor( LVisitor ); for LIdx := 0 to ComponentCount - 1 do begin LVisitor.Visit( Components[LIdx] ); end; finally LVisitor.Free; end; end; procedure TMainView.PrepareVisitor( AVisitor : TVisitor ); begin AVisitor.Clear; AVisitor.RegisterType<TButton>( procedure( Instance : TButton ) begin Instance.Caption := 'a button'; end ); AVisitor.RegisterType<TEdit>( procedure( Instance : TEdit ) begin Instance.Text := 'an edit'; end ); AVisitor.RegisterType<TLabel>( procedure( Instance : TLabel ) begin Instance.Caption := 'a label'; end ); AVisitor.RegisterType<TMemo>( procedure( Instance : TMemo ) begin Instance.Clear; Instance.Lines.Add( 'a memo' ); end ); end; end.
Delphi-Quellcode:
unit Visitor;
interface uses System.SysUtils, System.Generics.Collections; type IVisitorHandler = interface ['{7C5BA846-6286-406A-AC87-3BC89F2E9F21}'] procedure Visit( const Instance : TObject ); end; IVisitorHandler<T : class> = interface( IVisitorHandler ) end; TVisitor = class private FVisitorDict : TDictionary<TClass, IVisitorHandler>; public constructor Create; destructor Destroy; override; procedure RegisterType<T : class>( AVisitor : IVisitorHandler<T> ); overload; procedure RegisterType<T : class>( AVisitor : TProc<T> ); overload; procedure Clear; procedure Visit( Instance : TObject ); end; TVisitorHandler = class abstract( TInterfacedObject, IVisitorHandler ) protected procedure Visit( const Instance : TObject ); virtual; abstract; end; TVisitorHandler<T : class> = class abstract( TVisitorHandler, IVisitorHandler<T> ) end; TAnonVisitorHandler<T : class> = class( TVisitorHandler<T> ) private FVisitor : TProc<T>; protected procedure Visit( const Instance : TObject ); override; public constructor Create( AVisitor : TProc<T> ); end; implementation { TVisitor } procedure TVisitor.Clear; begin FVisitorDict.Clear; end; constructor TVisitor.Create; begin inherited; FVisitorDict := TDictionary<TClass, IVisitorHandler>.Create; end; destructor TVisitor.Destroy; begin FVisitorDict.Free; inherited; end; procedure TVisitor.RegisterType<T>( AVisitor : TProc<T> ); begin RegisterType<T>( TAnonVisitorHandler<T>.Create( AVisitor ) ); end; procedure TVisitor.RegisterType<T>( AVisitor : IVisitorHandler<T> ); begin FVisitorDict.AddOrSetValue( T, AVisitor ); end; procedure TVisitor.Visit( Instance : TObject ); var LClass : TClass; begin LClass := Instance.ClassType; while Assigned( LClass ) do begin if FVisitorDict.ContainsKey( LClass ) then begin FVisitorDict[LClass].Visit( Instance ); Break; end; LClass := LClass.ClassParent; end; end; { TAnonVisitorHandler<T> } constructor TAnonVisitorHandler<T>.Create( AVisitor : TProc<T> ); begin inherited Create; FVisitor := AVisitor; end; procedure TAnonVisitorHandler<T>.Visit( const Instance : TObject ); begin FVisitor( Instance as T ); end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:13 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz