![]() |
Datenbankapplikation als 3 Schichtenmodell
Hallo,
ich beschäftige mich grade mit der Theorie des Softwareentwurfs. Ein Modell für den Entwurf besteht aus dem Drei-Schichtenmodell. 1. Benutzerschnittstelle 2. Objektmodell 3. Datenbankzugriff Ich frage mich nun wie das ganze in einer Datenbankanwendung aussieht. Wie trenne ich Datenbankzugriff und Objektmodell, wenn ich mit Komponenten wie myDAC arbeite? Diese sind ja letztendlich für den DB-Zugriff zuständig. Wie hat dann das Objektmodell auszusehen? Muss ich jedes Tupel meiner Datenbank als Objekt darstellen? D.h. jede Tabelle mit allen Tupeln als Objekte kapselt und die bei veränderungen in die DB zurückschreiben? Kann mich mal jemand aufklären, in welche Richtung ich denken sollte? Danke! |
Re: Datenbankapplikation als 3 Schichtenmodell
Ich würde das wie folgt lösen:
1) Für jede Tabelle eine eigene Klasse, die die Zugriffe auf die DB kapselt. Dabei wird der Zugriff über Methoden gesteuert (z.B. SelAlles, Insert, Update, Delete, CopyToRec, CopyToLst) 2) Für jeden Datensatz eine eigene Klasse, die für jedes Feld aus der DB eine eigene Eigenschaft hat. Objekte davon werden an die entspr. Methoden der Tabellenklasse übergeben (z.B. TTabelleTest.CopyToRec(Rec:TDatensatzTest);) 3) Für jede Tabelle sollte es eine eigene Objektlisten-Klasse geben, die nur mit Objekten des richtigen Typs arbeiten sollte. Dadurch kann die Klasse dann auch tabellenspezifische Methoden haben. (z.B. SucheNachPrimaryKey...) Wenn die Datensätze erstmal im Speicher als Objekte vorliegen kannst Du damit alles machen, was Du willst. Du kannst sogar eigene Klassen bauen, die z.B. zwei TDatensatzTest-Objekte enthalten. Eine als Original, eine als Arbeitskopie. Dadurch lässt sich dann später feststellen, ob es tatsächlich eine Änderung an den Daten gegeben hat... |
Re: Datenbankapplikation als 3 Schichtenmodell
Hallo,
hmm, das klingt ja schon ganz richtig. Nur: wie spielen dann die DB-Komponenten eine Rolle? Dann wird es wohl unmöglich sein Komponenten wie DBGrid oder ähnliches zu verwenden!? Oder? Wie spielen diese Komponenten dann mit? Außerdem: Wann speichere ich die Änderungen im Objektmodell in der DB? Wenn die Indirektstufe mehr drin ist, werde ich ein Problem mit dem Sperren von Datensätzen haben: Vor dem Editieren muss direkt auf die DB zugegriffen werden, um Sperren zu erkennen, da kann ich nicht im Objektmodell rumeditieren...? |
Re: Datenbankapplikation als 3 Schichtenmodell
Die TQuery-Komponente steckt in den Tabellenklassen (für die Zugriffe).
Datensensisitve Komponenten (TDB...) können (und brauchen) nicht mehr verwendet werden -> mehr Freiheit beim Design der Oberfläche. Das Arbeiten mit einem mehrschichtigen Modell muss natürlich im Aufbau der DB berücksichtigt werden. Die einfachste Variante: In jeder Tabelle gibt es für einen Datensatz ein Feld mit einer Versionsnummer. Diese wird per Trigger bei jedem Update (BEFORE UPDATE) autom. inkrementiert. Stellt der gleiche Trigger fest, das die in der DB eingetragene Versionsnummer ungleich der einzutragenen Versionsnummer ist wird ein datenbankseitiger Fehler ausgelöst. Die Anwendung kann dann darauf reagieren und unter Umständen jetzt sogar die Daten aus dem Speicher und die (inzwischen) geänderten Daten aus der Datenbank gegenüberstellen. Das ist natürlich Mehraufwand, der allerdings durch viel Flexibilität mehr als wett gemacht wird. |
Re: Datenbankapplikation als 3 Schichtenmodell
Hallo,
d.h., da es keine direkte Verbindung von Oberfläche und DB habe, kann ich datensensitive Komponenten nicht mehr verwenden(DBGrid, DBLookupbox,...)? Was bedeutet ich muss alle Komponenten für die Darstellung 'neu erfinden'? Den Vorteil verstehe ich noch nicht: wenn meine Applikation startet muss ich die benötigten Daten über die DBKomponenten in transistente Objekten speichern (TTabellenObjekt, TKundenObjekt,...). Für die Darstellung dieser Objekte im Userinterface muss ich dann selbst sorgen!? Wenn ich z.B. einen Kunden editieren will, greife ich auf das entsprechenden Objekt z.B. Tabelle.Kunde zu. Ist so ein 'liveRequest' überhaupt möglich? Recht es nicht eine Indirektstufe mehr einzuführen? So das ein Objekt den DB-Zugriff lediglich kapselt? Dann könnte ich zumindest die DB-sensitiven Komponenten nutzen. So wäre dann jeder Zugriff auf eine DB-Tabelle mit DB-Komponente über den Objektlayer gekapselt. In jedem aus der DB erzeugten Objekt TTabelle wäre dann die DB-Komponente oder ein Verweis auf diese enthalten(?!?). |
Re: Datenbankapplikation als 3 Schichtenmodell
Meine Idee ist natürlich nur eine Möglichkeit - die ich allerdings schon seit einiger Zeit einsetze und nie auf nennenswerte Probleme gestossen bin.
Es ist richtig, dass es keine direkte Verbindung zwischen Datenbank und Oberfläche gibt. Allerdings müssen keine neuen Komponenten 'erfunden' werden. Da Du völlig oberflächenunabhängig mit den Daten aus der DB umgehst kannst du jede beliebige Komponente verwenden (z.B. TEdit, etc.). Bei Programmstart dürfen nur die Daten aus Lookup-Tabellen geladen werden, da diese sich in der Regel während eines normalen Programmlaufs nicht ändern werden. Alle anderen Daten müssen "on demand" geladen (und auch wieder gespeichert werden). Ein Beispiel: 1) Es wird eine Suche über den Kundennamen durchgeführt. Deine Tabellen-Klasse setzt das SQL-Statement ab. Hinterher werden alle gefundenen Sätze in einer Objektliste abgelegt. Diese Daten werden beliebig (z.B. in einem Listview) angezeigt. 2) Der User wählt einen Kunden per Doppelklick aus dem Listview aus. Im Hintergrund werden alle erstmal notwendigen Daten aus der DB in den Speicher geladen (was mit "prepared"-Statements blitzschnell gehen sollte). Danach erfolgt wieder die Anzeige auf der Oberfläche (egal in welchen Komponenten). Falls der User jetzt Daten bearbeitet müssen natürlich nur die Datensätze, die geändert wurden zurückgeschrieben werden. Dabei werden alle Felder des Datensatzes geupdatet. Auch die, die sich eigentlich nicht geändert haben. Zeitlich sollte man das vernachlässigen können. Die einzige Frage, die zu klären wäre ist WANN die DB-Updates zu machen sind. Und das ist abhängig vom Programmierer. Ich mache es z.B. immer, wenn das entspr. Fenster (auf dem die Editierung stattgefunden hat) geschlossen werden soll. |
Re: Datenbankapplikation als 3 Schichtenmodell
Hallo,
ich versuche das zu verstehen. Ich nehme an beliebige Komponenten heißt beliebige nicht datensensitive? Wenn ich DB-Zugriffskomponenten verwende, verfüge ich dann nicht schon über die Trennung Datenbankzugriff-Objektmodell-Applikation? Wenn ich die Komponenten für den Zugriff zur Laufzeit erzeuge, für jede Tabelle ein Objekt, sind dies dann nicht meine transienten Objekte der mittleren Schicht? |
Re: Datenbankapplikation als 3 Schichtenmodell
Im grunde ja. Die 2. und die 3. Schicht verschmelzen hier ein wenig:
1. Benutzerschnittstelle Alle (nicht datensensitiven) Komponenten, mit denen der User arbeiten kann (Listen, Eingabefelder, etc.) 2. Objektmodell Abbildung eines Datensatzes einer Tabelle in einer Klasse.
Delphi-Quellcode:
3. Datenbankzugriff
TDatensatzPerson = class(TObject)
protected FNachname: String; FVorname: String; public property Nachname: String read FNachname write FNachname; property Vorname: String read FVorname write FVorname; end; Klasse, die den Zugriff auf eine Tabelle kapselt
Delphi-Quellcode:
TTabellePerson = class(TObject)
protected FQuery: TQuery; public . . . public procedure SelAlles; procedure CopyToRec(iRec: TRecDatensatzPerson); end; implementation . . . procedure TTabellePerson.SelAlles; begin FQuery.Close; FQuery.SQL.Text:= 'select * from person'; FQuery.Open; end; procedure TTabellePerson.CopyToRec(iRec: TRecDatensatzPerson); begin iRec.Nachname:= FQuery.FieldByName('Nachname').AsString; iRec.Vorname:= FQuery.FieldByName(Vorname).AsString; end; |
Re: Datenbankapplikation als 3 Schichtenmodell
Hallo,
ok, so weit gut. Wenn das jetzt richtig verstehe, könnte ich die Db-Zugriffskomponenten in einem Objekt kapseln. Jenes enthält dann jeweils die Query für die entsprechende Tabelle. Möchte ich die gesamte Ergebnismenge erhalten, könnte ich folgendes machen:
Delphi-Quellcode:
Wobei 'selectall' mir die gesamte Ergebismenge liefert. Dafür müsste 'SelectAll' dann eine Funktion sein, die mir eine Datenmenge liefert.
...
var myTabellePerson: TTabellePerson; ... Ergebnismenge:= myTabellePerson.Selectall; Was spricht dagegen, wenn mir diese Funktion die Ergebnismenge in Form vom Typ TDatasource zurückliefert? Dann könnte ich diese Ergebnismenge direkt mit einem DBGrid verbinden. Oder ist das wieder ein Aufbruch der Trennnung? |
Re: Datenbankapplikation als 3 Schichtenmodell
Zitat:
Ein Aufruf sähe etwa so aus:
Delphi-Quellcode:
Es gibt eine strikte Trennung zwischen Datenzugriff (alles in TTabelle...) und den eigentlichen Daten (TObjektListe..., bzw. TDatensatz...).
...
var myTabellePerson: TTabellePerson; myListePerson: TObjektlistePerson; ... myTabellePerson.Selectall; myTabellePerson.CopyToLst(myListePerson); for i:=0 to myListePerson.Count-1 do begin ... // Anzeige der Daten auf der Oberfläche (z.B. Listview) end; |
Re: Datenbankapplikation als 3 Schichtenmodell
Hi,
ok, ich bin mir zwar nicht sicher ob ich alles verstanden habe, werde es mir aber mal durch den Kopf gehen lassen. Danke dir vielmals! Weitere Kommentare sind gern gesehen...;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:30 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