AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Object Daten-Layer

Ein Thema von hanspeter · begonnen am 14. Feb 2011 · letzter Beitrag vom 14. Feb 2011
Antwort Antwort
hanspeter

Registriert seit: 26. Jul 2003
Ort: Leipzig
1.350 Beiträge
 
Delphi XE2 Professional
 
#1

Object Daten-Layer

  Alt 14. Feb 2011, 10:33
Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDAC
Hallo,
für ein größeres Projekt halte ich die Daten in einem Object und bräuchte hier mal einen Denkanstoß.
Beispiel eine Kundenadresse.
Delphi-Quellcode:
TKunde=class
private
  fid : integer;
  fplz : string;
  fort : string;
public
  procedure Load(ID: Integer);
  procedure Save;
  property id : integer read fid write fid;
  property plz: string read fplz write fplz;
  property ort: string read fort write fort;
end;
Load läd eine Adresse aus der Datenbank.
Save soll nur Änderungen speichern.
Also z.B.
Delphi-Quellcode:
Kunde.Load(1234);
Kunde.Plz := 1234;
Kunde.Save
;

Mir geht es jetzt darum, wie löse ich am elegantesten (und schnellsten) das Problem festzustellen ob und welche Felder geändert wurden.
Mir fallen hier zwei Methoden ein.

1. Setter für jeden Property.
Delphi-Quellcode:
procedure TKunde.SetPlz(Val: String);
begin
  if Val <> fPLZ then plzChange := true;
  fPLZ := Val;
end;
Da hat den Nachteil, das ich für jede property einen eigenen Setter schreiben muss.

2. Orginalwerte aus der Datenbank speichern und jedes Feld doppelt halten.
In der Procedure Save dann die Feldinhalte vergleichen.

if fPLZ <> OrgPLZ then ...

Eine weitere Überlegung ist das Füllen dieses Objektes mit Daten aus der Datenbanktabelle.
Ist nachfolgender Weg praktikabel?

Alle lokalen Felder haben den gleichen Namen wie die Datenbankfelder und bekommen einen Präfix (z.B. "f")
Mit "Select * from Tabelle WHERE ID=:ID wird der gewünschte Satz selektiert. Die Wertzuordnung erfolgt über RTTI zur Laufzeit.

Hat wer noch einen anderen Vorschlag?

Ich möchte mir einen kleinen Geerator schreiben, der die lokale Feldliste und die Propertys aus der Select-Anweisung generiert.
Die Klasse erledigt noch andere Aufgaben.
Funktionsfähig ist bereits das Füllen und Auslesen der Daten in einer Bildschirmmaske.

Für ein paar Ideen oder Denkanstöße wäre ich dankbar.

Gruß
Peter
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.381 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Object Daten-Layer

  Alt 14. Feb 2011, 11:07
hi,

was mir ganz spontan einfällt: Mach ein Stringlist in der Du KEy=Value die Änderungen protokollierst, d.h. im Setter des property musst Du die Property und den neuen Wert in die Stringlist speichern. Beim Save gehst Du dann die Stringlist durch und speicherst die entsprechende Werte in der DB.

Wenn Du alle Änderungen in der SL speicherst könntest Du darüber auch eine Undo-Funktion bauen.


Füllen des Objekets: Klar über RTTI. den Präfix würde ich persönlich weglassen (was soll das F?) oder die ungarische Notation verwenden.
Problem dabei ist aber, dass in Datenbanken die Länge der Feldnamen beschränkt sein könnte (z.B. in Firebird) - in diesem Fall also kurze Feldnamen verwenden oder über eine Zuordnungsliste gehen (FeldnameDB=PropertyName) oder über die Attribute (wenn die neue RTTI verwendet wird).

Grüße
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Object Daten-Layer

  Alt 14. Feb 2011, 11:22
wie wäre es damit
Beim Lesen aus der DB müssen natürlich beide arrays (FOldData, FNewData) mit den Werten aus der DB befüllt werden.
Beim Speichern kann man nun diese Daten vergleichen.

Hieraus lässt sich auch schön eine Basisklasse bilden und die abgeleitete hat eigentlich nur noch die properties und benutzt die Getter/Setter der Basisklasse
Delphi-Quellcode:
type
  TKunde = class
  private
    FOldData = array of variant;
    FNewData = array of variant;
    procedure InternalSetter( index : integer; Value : Variant );
    function InternalGetter( index : integer ) : Variant;
  protected
    procedure SetIntData( index : integer; const Value : integer );
    function GetIntData( index : integer ) : integer;
    procedure SetStrData( index : integer; const Value : string );
    function GetStrData( index : integer ) : string;
  public
  published
    property id : integer index 0 read GetIntData write SetIntData;
    property plz : string index 1 read GetStrData write SetStrData;
    property ort : string index 2 read GetStrData write SetStrData;
  end;

procedure TKunde.InternalSetter( index : integer; Value : Variant );
begin
  FNewData[ index ] := Value;
end;

function InternalGetter( index : integer ) : Variant;
begin
  Result := FNewData[ index ];
end;

procedure TKunde.SetIntData( index : integer; const Value : integer );
begin
  InternalSetter( index, Value );
end;

function TKunde.GetIntData( index : integer ) : integer;
begin
  Result := VarToInt( InternalGetter( index ) );
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#4

AW: Object Daten-Layer

  Alt 14. Feb 2011, 11:30
Wenn id den PK darstellt, dann würde ich die Property ReadOnly deklarieren, da der Wert ja vermutlich über einen Trigger und Generator befüllt wird statt durch Zuweisung.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Object Daten-Layer

  Alt 14. Feb 2011, 11:37
Wieso, hängt von der Anwendung ab und Update dann so
Code:
UPDATE MeineTabelle SET id = :NewID WHERE id = :OldID
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#6

AW: Object Daten-Layer

  Alt 14. Feb 2011, 11:43
Ich gehe davon aus, dass ID ein künstlicher Schlüssel (PK) ist, der vom DBMS generiert wird. Den würde ich in den meisten Fällen nicht überschreiben wollen, mir fällt auch kein guter Grund für ein solches Überschreiben ein. Deshalb mein Vorschlag einer ReadOnly-Property, es sei denn, es ist ganz anders gemeint bzw. gewollt.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Object Daten-Layer

  Alt 14. Feb 2011, 12:01
Ich gehe davon aus, dass ID ein künstlicher Schlüssel (PK) ist, der vom DBMS generiert wird. Den würde ich in den meisten Fällen nicht überschreiben wollen, mir fällt auch kein guter Grund für ein solches Überschreiben ein. Deshalb mein Vorschlag einer ReadOnly-Property, es sei denn, es ist ganz anders gemeint bzw. gewollt.
Es kommt halt drauf an, wer die Datenhoheit hat
Und in seinem Beispiel war id nicht ReadOnly
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
hanspeter

Registriert seit: 26. Jul 2003
Ort: Leipzig
1.350 Beiträge
 
Delphi XE2 Professional
 
#8

AW: Object Daten-Layer

  Alt 14. Feb 2011, 12:25
Die ID ist nur ein Beispiel. Im konkreten Fall wird diese von einem Datenbank-Generator erzeugt und ist readonly.
Die Idee mit einer Stringlist würde bedeuten, dass ich alle Variablen in string wandeln müsste. Also auch z.B. boolean.
Die Idee mit dem Array of Variant ist überlegenswert, bringt allerdings mehr Speicheroverhead mit. Geschwindigkeit sollte im Datenbankbereich hier
vernachlässigbar sein.

Bei meinem Präfix "f" gibt es wohl ein kleines Missverständnis.
Ich wollte die Property so wie in der Datenbank benennen und die zugehörige private Variable dann mit einem Präfix versehen.
In C# geht das hier etwas eleganter.
Ich hatte auch bereits einmal probiert für jedes Field ein TField zu verwenden, das ist aber ein ziemlicher Overhead. Den Feldnamen über RTTI zu bestimmen ist hier eleganter.

Im Moment baue ich wie gesagt einen kleinen Generator, der mir aus einer Kommentarzeile den Quelltext der Klasse (die Propertys) generiert.

Beispiel : { Field= ID,NAME,VORNAME,PLZ,ORT,STRASSE,TELEFON TABLENAME= Archiv PrimaryKey= ID}

Mit einem Array of Variant müsste ich dann noch aus der Query die Typinformation des Feldes auslesen und abspeichern.

Kleiner Nachtrag.
Kann ich über RTTI eigentlich den Feldindex der Propertie auslesen?


Gruß
Peter
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:20 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