Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Dataset als Parameter mit OOP oder wie ? (https://www.delphipraxis.net/40364-dataset-als-parameter-mit-oop-oder-wie.html)

Hansa 14. Feb 2005 20:39

Datenbank: IB/FB • Zugriff über: hierfür egal

Dataset als Parameter mit OOP oder wie ?
 
Hi,

ich habe hier verschiedene Forms die dienen zum Ausgeben von Listen. Die gleichen sich schon ziemlich, aber sind nicht identisch. Insbesondere die auzugebenden Daten sind natürlich unterschiedlich. Hierzu habe ich mir eine Klasse gebaut, die ganz grob so aussieht :

Zitat:

Zitat von Pseudocode
ErmittleDaten;
ZeigeKopf;
ZeigePositionen;
ZeigeFuss;

Die Prozeduren sind anfangs leer und werden nach Bedarf von den Nachkommen gefüllt / überschrieben usw. Nur, wo bringe ich jetzt da allgemeingültig das Dataset rein ?

Das wird schon überall gebraucht, ist aber immer eine andere Tabelle. 8) Ich habe nun in der Ursprungsform folgendes stehen :

Delphi-Quellcode:
  ErmittleDaten (DS); // DS ist als VAR Parameter deklariert.
  while not DS.Eof do begin
    ZeigePositionen;
    DS.Next;
  end;
Ich wollte DS erst später konkret besetzen. So scheint es aber nicht zu gehen. Wo muß das DS hin um es später je nach Lage zu nutzen ? So wie es hier steht gibt es nur AVs.

MrSpock 14. Feb 2005 21:15

Re: Dataset als Parameter mit OOP oder wie ?
 
Hallo Hansa,

wie hast du denn ErmittleDaten deklariert?

Delphi-Quellcode:
  procedure ErmittleDaten(DS: TDataSet);
Ist es als Methode zu deiner Klasse oder als globale Prozedur deklariert? Wie sieht der Body der Methode aus?

Hansa 14. Feb 2005 23:33

Re: Dataset als Parameter mit OOP oder wie ?
 
Delphi-Quellcode:
procedure ErmittleDaten(var DS: TDataSet);
Bei mir ist vieles in protected untergebracht :mrgreen: und auch das :

Delphi-Quellcode:
  protected
    DS : TDataset;
Ist natürlich ein FIBdataset, aber das ist egal.

Eben weil ich es später noch brauche. Momentan ist der Stand eben so, daß ich die ganze Prozedur auch leer lassen könnte und schreibe in einem Nachfahren das Dataset im Klartext da rein. Das will ich aber nach Möglichkeit umgehen, denn ich brauche nur einen Platzhalter, der nach Bedarf besetzt wird und dann könnte ich die "ErmittleDaten" Prozedur allgemein halten und nur das jeweilige Dataset verwenden.

Robert_G 14. Feb 2005 23:45

Re: Dataset als Parameter mit OOP oder wie ?
 
Warum sollte das protected sein? :gruebel:
Du hast sicher eine abstrakte Basisklasse...
Die bekommt ein privates Feld fDataSet vom Typ TDataSet. Dazu eine öffentliche oder protected readonly Property DataSet.
Der Constructor der Basisklasse schuckt ein const aDataSet :TDataSet und besetzt damit fDataSet. Warum sollten die Nachfahren auch diekten Zugriff darauf haben? :gruebel:

Sprint 14. Feb 2005 23:49

Re: Dataset als Parameter mit OOP oder wie ?
 
Zitat:

Zitat von Hansa
[...]denn ich brauche nur einen Platzhalter, der nach Bedarf besetzt wird und dann könnte ich die "ErmittleDaten" Prozedur allgemein halten und nur das jeweilige Dataset verwenden.

Warum machst du das nicht über Eigenschaften?

Delphi-Quellcode:
type
  TVorfahre = class
  private
    FDataset: TDataSet;
  protected
    procedure ErmittleDaten; virtual; abstract;
    procedure ZeigeKopf; virtual; abstract;
    procedure ZeigePositionen; virtual; abstract;
    procedure ZeigeFuss; virtual; abstract;
    property Dataset: TDataSet read FDataset write FDataset;
  end;
Delphi-Quellcode:
type
  TNachkomme = class(TVorfahre)
  ...
  public
  ...
    property Dataset;
  end;

Hansa 15. Feb 2005 00:49

Re: Dataset als Parameter mit OOP oder wie ?
 
So, Thx, das geht jetzt so weit. Property war tatsächlich das, was ich vermißt hatte. Es wird schon mal compiliert. :mrgreen: Allerdings kommt noch AV beim ersten Zugriff auf "Dataset".

Das muß doch wohl noch irgendwo her kommen bzw. erzeugt werden. Wenn das noch jemand wüßte, wäre echt nett. Für jetzt reichts mir erst mal. 8)

Lemmy 15. Feb 2005 06:10

Re: Dataset als Parameter mit OOP oder wie ?
 
Hi,

das DataSet über eine Property zu setzen ist nicht wirklich gut. Wenn dann sollte das über den Konstruktor laufen:

constructor create(DS:TFIBDataSet);

Grüße
Lemmy

Hansa 15. Feb 2005 12:24

Re: Dataset als Parameter mit OOP oder wie ?
 
Was ? Nicht wirklich gut ? :shock: Dann muß ich anders fragen : was ist besser ? :lol: Ich habe das ja auch nur mit property gemacht, weil Sprint und Robert_G gesagt haben, so sollte ich es machen. :mrgreen:

Soweit scheint das ganze ja auch zu gehen, bis auf die Zugriffsverletzung, weil das Ding wohl nicht initialisiert ist. Ich muß doch bestimmt zumindest den Tabellennamen mit angeben. Was überhaupt alles ?

Eigentlich hatte ich vor dem property-Dataset ein konkretes aus meinem Datenmodul zuzuweisen. Also so :

Delphi-Quellcode:
Dataset := KundeDS; // Dataset : property KundeDS : aus Datemodul
Hierbei kommt dann Zugriffsverletzung :

Delphi-Quellcode:
Dataset.close;
Das ist der erste Zugriff auf "Dataset" überhaupt.

Robert_G 15. Feb 2005 12:26

Re: Dataset als Parameter mit OOP oder wie ?
 
Wie? Was? Wo?
Hast du dir überhaupt meinen Post durchgelesen? :roll:

Hansa 15. Feb 2005 12:42

Re: Dataset als Parameter mit OOP oder wie ?
 
Ich bräuchte ein Beispiel für den Constructor. Momentaner Stand ist, daß ich das von Sprint so umgesetzt habe. Also habe ich statt meines konkreten Datasets eben "Dataset" da stehen, kann aber nicht drauf zugreifen. Mit ein paar Wörtern alleine komme ich so nicht weiter. Wo muß der Konstruktor genau hin ? Wie sieht er konkret aus ?

Bzw. um es nochmals zu sagen : wie teile ich meinem Programm mit, daß es sich an einer Stelle bei Dataset um den Lagerbestand handelt und woanders z.B. um eine Adresse ?

Lemmy 15. Feb 2005 13:05

Re: Dataset als Parameter mit OOP oder wie ?
 
Hi Hansa,


muss mich entschuldigen! Ich übergebe dem Konstruktor kein DataSet, sondern die Datenbankverbindung mittels der IBDatabase oder der IBTransaction:

also hier mal ein Beispiel (mit IBX, was aber nichts zur Sache tut):


Delphi-Quellcode:
type TDBObject=class(TObject)
     private
     protected
       iID:Int64;
       IBDataSet:TIBDataSet;
       sSQL, sSaveSQL:String;
       bSave, bExpicitTransaction:Boolean;
       Transaction:TIBTransaction;


       procedure SetSQLStatement; virtual;
       procedure SaveValues;      virtual;
       procedure SelectValues;    virtual; abstract;
       procedure SetValues;    virtual;

     public
       constructor create(DefaultDataBase:TIBDataBase); overload;
       constructor create(DefaultTransaction:TIBTransaction); overload;

       procedure Free; virtual;

       procedure Save;

       property SaveDB:Boolean read bSave write bSave;
       property ID:Int64 read iID;
     end;
und hier die abgeleitete Klasse:

Delphi-Quellcode:
type TAdresse=class(TDBObject)
     private
       sName, sStrasse, sOrt, sTelefon, sFax, sAnrede, sTitel, sAnschrift:String;
     protected
       procedure SelectValues; override;
     public
       constructor create(DefaultDataBase:TIBDataBase; AdresseID:Int64);
       property Name:String read sName write sName;
       property Strasse:String read sStrasse write sStrasse;
       property Ort:String read sOrt write sOrt;
       property Telefon:String read sTelefon write sTelefon;
       property Fax:String read sFax write sFax;
       property Anrede:String read sAnrede write sAnrede;
       property Titel:String read sTitel write sTitel;
       property Anschrift:String read sAnschrift;
     end;
Im Konstruktor der Klasse TDBObject wird je nach aufgerufenen Konstruktor eine IBDataSet oder eine IBTransaction + IBDataSet erzeugt und natürlich beim Destruktor wieder freigegeben. Ich habe so einige Klassen erzeugt, teilweise auch mit Enkeln (wie nennt man das, wenn man eine Klasse ableitet und von dieser wieder ableitet?).

Die Übergabe der IBDataSet bzw. Transaction mache ich deshalb, um zum einen bei der IBDataset innerhalb der Klasse die Transaktionssteuerung zu machen, oder wenn ich die Transaction-Instanz übergebe wird die Transaktionssteuerung außerhalb der Klasse vorgenommen (wenn das Objekt der Klasse z.B. von einem anderen Objekt (z.B: Auftrag) aufgerufen wird).



Grüße
Lemmy

Hansa 15. Feb 2005 21:04

Re: Dataset als Parameter mit OOP oder wie ?
 
Lemmy, das ist ja schon gut, aber ich kann doch nicht auf niedriger Objekt-Ebene schon solch komplizierte Gebilde einbauen. Ich will doch nur ein Dataset haben, welches ich nach Bedarf durch ein geeignetes und auch schon definiertes ersetze. Sogar die Feldnamen sind fast identisch, aber nicht alle.

Sprint 15. Feb 2005 21:10

Re: Dataset als Parameter mit OOP oder wie ?
 
Zitat:

Zitat von Hansa
wie teile ich meinem Programm mit, daß es sich an einer Stelle bei Dataset um den Lagerbestand handelt und woanders z.B. um eine Adresse ?

Stichwort: Eigenschaften.

Lemmy 16. Feb 2005 06:43

Re: Dataset als Parameter mit OOP oder wie ?
 
Guten Morgen,

was heißt hier niedrige Objektebene? Wieviele Nachfahren von TDBObject willst Du denn erzeugen? Die Klasse TAdresse ist mein Ziel, dort steckt alles drin, was ich in dieser Anwendung benötige. Neben TAdresse gibts noch ein paar andere. Lediglich bei einer Klasse habe ich mich zu ner weiteren Vererbung entschlossen, da ich diese universell einsezten muss:

Delphi-Quellcode:
type THoaiAnsatz=Class(TDBObject)
     protected
       sHoaiAnsatzNr, sAuftragNr, sBeschreibung, sBearbeiter, sStrasse, sOrt, sTeilort,
       sSonstiges, sPLZ:String;
       cSchaetzung, cBerechnung, cAnschlag, cFeststellung:Currency;
       cSchaetzungHonorar, cAnschlagHonorar, cFeststellungHonorar, cBerechnungHonorar:Currency;
       cMwst, cBesondereLeistungen, cLeistungsbild, cNebenkosten, cAbschlag:Currency;
       cNebenPauschale, cBLWiederholungen:Currency;

       iHoaiZone, iHoaiZuschlag:SmallInt;
       iHoaiTeilID:SmallInt;

       dtDatum:TDate;

       iAuftraggeberID, iHoaiVorlageID, iAuftragID:Int64;
       adrAuftraggeber:TAdresse;
       sHoaiVorlage:String;

       AnrechenbareKost:THoaiAnrechenbareKosten;
       IBDatabase:TIBDatabase;

       cGrundhonorar:Currency;

       iObjektID:Int64;

       sBegruendung:TStringList;

       procedure SelectValues; override;
       procedure SetValues; override;
       function GetNebenkostenHonorar:Currency; virtual;
       procedure SetSQLStatement;

     public
       constructor create(DefaultTransaction: TIBTransaction; HOAIAnsatzID:Int64);
       procedure free;  override;

       procedure saveValues; override;

       property AnsatzNummer:String read sHoaiAnsatzNr;
       property AuftragNummer:string read sAuftragNr;
       property Beschreibung:String read sBeschreibung;
....

und deren Ableitungen:

Delphi-Quellcode:
type THoai2Ansatz=Class(THoaiAnsatz)
     protected

       IBDataSetDetail:TIBDataSet;
       cVorplanungen, cEntwurfsplanungen:Currency;

       iWiederholungen:Integer;
       iVorplanung, iEntwurfsplanung:Integer;
       cUmbauzuschlag:Currency;
       cWiederholungenHonorar,cWiederholungenLB, cVorhandeneBausubstanz:Currency;

       sSQLDetail, sSaveSQLDetail:String;


       procedure SelectValues; override;
       procedure SaveValues; override;
       procedure SetValues; override;
       function GetNebenkostenHonorar:Currency; override;
       procedure SetSQLStatement;

     public
       constructor create(DefaultTransaction: TIBTransaction; HOAIAnsatzID:Int64);
       procedure free;  override;
...

Von den Ableitungen gibts derzeit 2, im Endausbau werden es wohl um die 12 werden.

Ein "allgemeingültiges" Objekt wirst Du nie erzeugen können, wenn Du durch das Objekt (z.B. Adresse:TAdresse) die Eigenschaften auslesen willst (Adresse.Name) Da kannst Du nicht einmal ne Adresse auslesen und ein anderes mal den Lagerbestand! Dazu brauchst Du spezielle Klassen, die sich der Gegebenheit der Tabelle anpassen.

Holger Klemt geht in seinem Artikel allerdings etwas neutraler an die Sache ran, was aber wieder bedeutet, dass schon bei der Erstellung der Datenbank auf diese Art des Datenbankzugriffs eingegangen werden muss!

Grüße
Lemmy

Hansa 16. Feb 2005 12:22

Re: Dataset als Parameter mit OOP oder wie ?
 
Ich glaube keiner versteht mich. :cry: Sprint vielleicht, aber das andere ist wohl viel komplizierter als überhaupt gebraucht. Also gut, ich bringe ein ausführlicheres Beispiel :

2 Ausgabe-Grids. Eines für Lager, das andere für Preise. In beiden Fällen brauche ich zuerst mal die Artikel und da fängts an. Die sind etwas kompliziert. Sie können 1-3 Zeilen für die Bezeichnung haben. Sie werden je nach Eigenschaften farblich gekennzeichnet usw. Jetzt habe ich das alles in einer separaten Unit. Die Anzeige sieht dann so aus :

Delphi-Quellcode:
ZeigePosition;
ZeigeDetailposition;
ZeigePosition zeigt die Artikel mit allem drum und dran an. ZeigeDetailposition dient zum Anzeigen entweder des Lagerbestandes oder des Preises.

ZeigeDetailPosition bleibt erst mal leer, weil erst später feststeht was jetzt angezeigt wird (also Lager oder Preis). Nun habe ich in den abgeleiten Klassen 2 Datasets PreisDS und LagerDS. Mit 2 verschiedenen Joins einmal über Lager und einmal über Preise. Die Ursprungsklasse kann davon aber noch nichts wissen. Meine Überlegung war, die Logik so in der Ursprungsklasse beizubehalten, aber eben mit einem leeren Dataset, daß erst später konkret besetzt wird.

Mit der Property ging das wohl schon so, bis auf die Tatsache, daß kein Zugriff darauf möglich ist. Es sieht also so aus, daß die Feldnamen bzw. die Daten für die Artikel in beiden Fällen gleich sind (das ganze läuft über einen Join (ARTIKEL JOIN LAGER bzw. ARTIKEL JOIN PREIS) und ich eben im Vorfeld alles was mit den Artikeln zu tun hat erledigen will. Würde das gelingen, so müßte ich nur noch in ZeigeDetaildaten die entsprechende Lagerdaten/Preise anzeigen.

ZeigePositionen ist nun gedacht zur Anzeige der immer gleichen Artkeldaten und das kann ich nicht nutzen, weil zum Schluß diese Daten in den Datasets LagerDS bzw. PreisDS drin stecken. Davon weiß eben die Grundklasse noch nichts. 8)

Hansa 17. Feb 2005 01:51

Re: Dataset als Parameter mit OOP oder wie ?
 
Tja, so ist Delphi. Phänomenal ! :shock: Es ist schon sehr erstaunlich, was da alles möglich ist, sofern man sich nur tief genug in die Problematik eingräbt, sucht und auch mal experimentiert. Um es vorwegzunehmen : vergesst die properties und den ganzen Rest.

Das geht so einfach, daß ich mich nicht traue zu sagen wie. Das ganze ist reproduzierbar und getestet anhand zweier Tabellen. Leider weiß ich noch nicht genau, worauf es letztendlich ankommt, aber im Großen und Ganzen ist es ziemlich klar.

Die grundlegende Programm- und Datenbankarchitektur spielt allerdings eine gewaltige Rolle. Ich schätze mal, daß sich der Aufwand, ein komplexes Ausgabe-Formular zu entwerfen (wie im konkreten Fall) auf 10 % der veranschlagten Zeit reduzieren läßt. Ich kann also im Laufe eines einzigen Tages 20 in Frage kommende Formulare so gestalten, daß alles paßt. Vom Wartungsaufwand dafür ganz zu schweigen. 8)

Sprint 17. Feb 2005 02:09

Re: Dataset als Parameter mit OOP oder wie ?
 
Hättest du hier eine richtige Frage gestellt, dann hättest du auch eine passende Antwort bekommen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08: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