@nahpets: Aus dem Ansatz komme ich eigentlich her. Ich hatte ein Datenmodul mit den Kopplungen zur Datenbank, etc. Dann kam ein Datenmodul dazu, mit einigen Optionen für das Hauptprogramm. Dann habe ich einen Kalender ergänzt, den ich aber erst mal eigenständig gebaut habe. Deshalb hat der sein eigenes Datenmodul. Und da wäre die Frage, wie man die am Besten miteinander koppelt bzw. was man am sinnvollsten übergibt (beim Kalender hatte ich die TpFIBDatabase als Parameter übergeben).
Meiner Meinung nach gehören allen Zugriffskomponenten für die Datenbank(en) in das Datenbankmodul. D. H.: Die anderen Module, Formulare... kennen die Datenbank(en) nicht, sie "wissen" nicht einmal, dass sie irgendwelche Daten von einer Datenbank erhalten.
Wenn Du mehrere Datenbanken benötigst, dann kapsle jede Datenbank in einem eigenen Datenmodul, sofern ansonsten die Übersichtlichkeit in einem Datenmodul darunter leiden sollte.
Meist gehe ich her und halte alle
SQL-Statements in einer Datenbanktabelle vor. Diese kann sich unter Umständen in einer eigenen Datenbank befinden, welche zur Steuerdaten enthält. Die "Nutz"-Daten befinden sich in einer eigenen Datenbank. Hierdurch lässt sich sehr einfach eine Mandantenfähigkeit realisieren. Alle nutzen gemeinsam die Datenbank mit den Steuerdaten, jeder Mandant hat seine eigene Nutzdatendatenbank. Steuerdatenbank und Nutzdatenbanken können sich dabei auf unterschiedlichen Datenbankservern befinden, z. B. ein Server für die Steuerdatenbank und ein Server für die Nutzdatenbanken, aber auch für jede Nutzdatenbank ein eigener Datenbankserver ist möglich. Was wo liegt uss hierbei natürlich (z. B. über eine INI-Datei) konfigurierbar sein. Bei mir gilt, wenn möglich, die Regel: Keine feste Verdrahtung der Datenbankverbindungen im Programm. Alles irgendwie sinnvoll und einfach (d. h.: anwender-
und administrator-
und entwicklerfreundlich - in dieser Reihenfolge) konfigurierbar halten.
Die
SQL-Statements sind, sofern erforderlich, parametrisiert. Jedes
SQL hat eine eindeutige ID. Werden nun (von wem auch immer) Daten aus der Datenbank benötigt, so erhält eine entsprechende Funktion im Datenmodul eine Anfrage.
Das einzige im Quelltext "festverdrahtete"
SQL-Statemant ist das Statement zum Holen der
SQL-Statements. Beim Wechsel des Datenbankherstellers muss ich daher nur die
SQL-Statements in der Datenbanktabelle (sofern erforderlich) syntaktisch an die ggfls. geänderten Bedingungen oder die andere Syntax anpassen. Am Programm sind keine Änderungen erforderlich. Hierdurch konnte ich vor Jahr und Tag mal eine recht komplexe und mandantenfähige Anwendung ohne Änderungen am Quellcode von DBase über Interbase und Oracle nach schließlich MS-
SQL-Server portieren. (Damals war die Nutzung der
BDE noch selbstverständlich). Irgendwann musste ich dann den Datenbankzugriff auf die
ADO-Komponenten umstellen. Hier waren dann nur Änderungen am Datenmodul notwendig.
Wie Du die Parameter für die Wherebedingungen... übergibst, muss Du selbst entscheiden. Hier fallen mir zwei bis drei Möglichkeiten ein:
Als Parameterliste an eine oder mehrere Funktionen des Datenmoduls. Dies kann recht schnell aufwändig werden.
Das Datenmodul "beauftragen" ein bestimmtes
SQL aus der Datenbanktabelle zu holen, dann im Modul, Formular... die Parameter befüllen, Das Datenbankmodul um Ausführung der Abfrage bitten und anschließend selbst das Ergebnis verarbeiten.
Mal nur so ungetestet hingedaddelt:
Delphi-Quellcode:
begin
...
if Datenmodul.GetSQL(SQLID)
then begin
Datenmodul.AbfrageQuery.Parameters.ParamByName('
Termin').Value := FTermin;
... was auch immer benötigt werden sollte
... Value ist vom Typ Variant, so dass hier nicht auch noch mit .AsIrgendwas gearbeitet werden muss
Datenmodul.AbfrageQuery.Parameters.ParamByName('
Name').Value := FName;
If Datenmodul.OpernQuery
then begin
// Die Daten der Abfrage in eigene Attribute, die Anzeige... übernehmen.
FTermin := Datenmodul.AbfrageQuery.FieldByName('
Termin').Value;
...
end else begin
// Hier ordentliche Fehlerbehandlung für den Fall, dass das Öffnen der Abfrage scheiterte.
end;
end else begin
// Hier natürlich dann eine sinnvollere Fehlerbehandlung.
// Allerdings darf in einer durchgetesteteten Programmversion dieser Fehler niemals
// auftreten, wenn doch, haben entweder der Programmierer oder der Datenbankadministrator
// Haue verdient.
ShowMessage(Format('
Das SQL mit der ID %d konnte nicht gefunden werden.',[SQLID]));
end;
...
end;
Für Insert, Delete und Update eine entsprechende Routine bauen, die dann kein OpenQuery macht sondern ein ExecSQL macht.
Alle direkten Datenbankzugriffe werden vom Datenmodul ausgeführt. Dieses behandelt alle Datenbankfehler und gibt, wenn nicht vermeidbar, anwenderfreundliche Fehlermeldungen zurück. Der Programmablauf sollte auch im Fehlerfalle störungsfrei weitergehen.
Alternative:
Eine Basisklasse erstellen, die alle Datenbankzugriffe kapselt. Alle Daten aus der Datenbank werden über abgeleitete Klassen verwaltet. Bei Änderungen an der Datenbank sind nur Änderungen in der Basisklasse erforderlich. Alle direkten Zugriffe auf die Datenbank sind in Funktionen dieser Basisklasse (einschließlich Fehlerbehandlung) gekapselt.
Welche Variante hier nun sinnvoll sein könnte, vermag ich nicht zu entscheiden, dafür fehlen zu viele Informationen über Art und Komplexität der Anwendung, da müsste man sich wohl die fachliche und die technische Seite erstmal das eine oder andere Stündchen grundlegen anschauen. Die grundsätzlich
immer beste Lösung gibt es wohl nicht
.