Datenbank-Zugriff auslagern in Datenmodul

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Joh
Lazarusforum e. V.
Beiträge: 280
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Datenbank-Zugriff auslagern in Datenmodul

Beitrag von Joh »

ok, ich erzeuge ein Datenmodul;
packe die Datenbank und die Transaction rein.

Dann im Formular die Connection auf Datenmodul.IBConnection setzen...
Soweit, so gut.
Klappt auch in der IDE, wenn ich die SQLQuery auf active setze; dann werden die Daten angezeigt.
Aber beim Ausführen kommt: Database not assigned...
Der Test war in einem funktionierendem Projekt, in dem ich einfach nur (!) ein Datenmodul erstellt habe und die Connection + Transaction verschoben habe.

wo liegt mein Fehler?
just my two Beer

Benutzeravatar
KoBraSoft
Beiträge: 123
Registriert: So 6. Jun 2021, 09:57
OS, Lazarus, FPC: die zu Zeit aktuellen Versionen, überwiegend Linux
CPU-Target: 64Bit 32 Bit
Kontaktdaten:

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von KoBraSoft »

Joh hat geschrieben: Sa 25. Mai 2024, 00:51 Dann im Formular die Connection auf Datenmodul.IBConnection setzen...
Du verwendest Firebird und SQLDB unter Windows?
Wie hast Du die Datenbank angebunden? Mit Dateiname und Pfad oder mit Alias in databases.conf?
Aber beim Ausführen kommt: Database not assigned...
wo liegt mein Fehler?
Offensichtlich ist zur Laufzeit keine Datenbank angebunden. Mehr kann ich aus deinen Angaben nicht herauslesen.
Mach ein Demo Projekt mit dem Fehler und stelle es hier ein, dann kann ich mehr sagen.
Konrad

www.KoBraSoft.de

Benutzeravatar
gladio
Beiträge: 223
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von gladio »

Die IBConnection muss wissen, wo die Datenbank zu finden ist.
Ich mache das meistens im OnCreate des Datamodule.
Entweder feste setzten: Connection.Database:= ..Pfad zur Dantenbank
und Connection.LibraryLacation:= ... ebenfalls den Pfad zur...DLL
oder, wenn das da nicht fest reingeschrieben werden soll, bietet sich eine INI-Datei an, aus der die Angaben ausgelesen werden.

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von charlytango »

Joh hat geschrieben: Sa 25. Mai 2024, 00:51 ok, ich erzeuge ein Datenmodul;
Ich nehme an, dass damit das Erstellen eines Datenmoduls in der IDE gemeint ist.
Joh hat geschrieben: Sa 25. Mai 2024, 00:51 Klappt auch in der IDE, wenn ich die SQLQuery auf active setze
Was diese Zeile für mich auch bestätigt.

Das Problem für das betreffende Formular (das dieses Datenmodul benutzt) ist, dass das Datenmodul bereits erstellt und an die DB angbunden sein sein muß damit es Daten liefern kann.

In den Projekteinstellungen Shift+Ctrl+F11 (Project - Project Options) kannst du nachsehen ob in der Position "Forms/Formulare" als Auto-Create Forms das Datenmodul vor dem Formular erzeugt wird.

Das automatische Erzeugen von Formularen (und ein Datenmodul ist "nichts anderes" als ein "unsichtbares Formular" um darauf nicht sichtbare Komponenten unterzubringen) bringt dann auch andere Herausforderungen.

Und du musst auch sicherstellen, dass die Datenbankverbindung zu dem Zeitpunkt in dem sie in der fertigen Applikation gebraucht wird auch aktiv ist.

Wenn du in der IDE zur Datenbank eine Verbindung herstellen kannst (wie du sagst) sollte das nur ein kleiner Schritt sein.

Meine Empfehlung: Lass die Komonenten für die Datenbankverbindung (also Connection + Transaction+ alle Hilfsfunktionen) im Datenmodul.

Das Datenmodul muss vor dem Formular erzeugt werden (entweder als Auto-Create Form oder manuell im Code)

Und du solltest dann noch zur Laufzeit im OnCreate oder OnActivate die Datenbankverbindung den TQueries zuweisen. Da verlasse ich mich nicht auf die IDE, das hilft auch wenn du im Laufe der Entwicklung das datenmodul gegen eine eigene Klasse tauscht, weil Vererbungen von Datenmodulen praktisch immer Probleme bringen..

Code: Alles auswählen

var
TQ:TQuery;
.....
  TQ.Close;
  TQ.Connection:=<Datenmodul>.<dieconnection>;
  TQ.SQL.Text:= 'SELECT .............';
  TQ.Open;
Diese Arbeiten packe ich meistens in eine eigene Prozedur

Wenn du Interesse an einem Beispielframework hast, findest du es hier

Joh
Lazarusforum e. V.
Beiträge: 280
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von Joh »

@kobrasoft, @gladio: Die Datenbank ist mit Dateiname und Pfad aus einer ini-Datei eingebunden.

charlytango hat geschrieben: Sa 25. Mai 2024, 10:22 Das Problem für das betreffende Formular (das dieses Datenmodul benutzt) ist, dass das Datenmodul bereits erstellt und an die DB angbunden sein sein muß damit es Daten liefern kann.

In den Projekteinstellungen Shift+Ctrl+F11 (Project - Project Options) kannst du nachsehen ob in der Position "Forms/Formulare" als Auto-Create Forms das Datenmodul vor dem Formular erzeugt wird.
:oops:
Danke, das wars...
Jedes Formular hatte ich bisher händisch in das Hauptprogramm eingetragen.
z.B. Application.CreateForm(TfrmArtikel, frmArtikel);
Das ich das auch mit dem Datenmodul machen muß, war mir eigentlich schon klar, bevor ich es benutzt hatte. Und dann trotzdem vergessen, wie bei gefühlt jedem 2. Formular.
Aber jetzt weiß ich jedenfalls, das automatisch erstellt genau das heißt, was ich manuell mache ;-)

Ich hatte mich immer schon gefragt, wozu diese Liste in den Projekteinstellungen gut sein soll^^


Dein Beispielframework werde ich mir angucken. Das ganze soll jetzt erstmal eh nur ein Test sein, um mögliche Nebenwirkungen frühzeitig zu erkennen.
just my two Beer

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von ErnstVolker »

Guten Morgen,

ich habe gerade mehr oder weniger das Gleiche Problem. Bei mir wird das Datenmodul vor allen Formularen und auch vor dem Hauptformular erzeugt. Ich verwende die ZEOS 8.0 Komponenten.

Als ich mit dem Projekt angefangen habe, hatte ich in TZConnection alle Vorgaben bezüglich der DB (Datenbankname, Host, LibraryLocation, Protocol, user, Passwort usw.) vorgegeben.

Jetzt hole ich die Vorgaben während "FormCreate" des Hauptformulares aus einer ini-Datei. Das klappt auch. Allerdings wenn ich das Passwort weglasse (das sollte nicht lesbar in einer ini stehen :shock: ) kommt beim Start des Programms eine Meldung (sinngemäß) "No Password supplied".

Was mich daran verwundert ist, dass noch übrhaupt kein "TZConnection.Connected" ausgeführt wurde. Das steht auf "False" und sollte erst nach drücken auf einen Anmeldebutton durchgeführt werden.
Scheinbar versucht sich die ZEOS-Connection-Komponente Vorgabe von Connected mit der DB zu verbinden. Wenn ich nämlich auch das Passwort in der ini-Datei vorgebe, dann klappt der Programmstart ohne gemecker.

Kennt jemand das Problem? Was mache ich hier falsch?

Viele Grüße und einen schönen Feiertag!

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von charlytango »

Aufgrund meiner Erfahrungen mit ZEOS 8.0 empfehle ich erst einen Test mit Lazarus 3.4 zu machen.
ErnstVolker hat geschrieben: Do 30. Mai 2024, 09:16 Bei mir wird das Datenmodul vor allen Formularen und auch vor dem Hauptformular erzeugt
Machst du das manuell über über die Reihenfolge der Auto-Create-Forms ?

Der Befehl zur Verbindung mit der Datenbank ist

Code: Alles auswählen

TZConnection.Connect
Wenn du Interesse an einem Beispielframework hast, findest du es hier
Es ist so gebaut dass man sehr leicht eine Verschlüsselung beim Schreiben/Lesen des INI Files einbauen kann, dann hast du das Problem des Klartextpassworts vom Tisch.
ErnstVolker hat geschrieben: Do 30. Mai 2024, 09:16 Kennt jemand das Problem? Was mache ich hier falsch?
Hier spielen einfach einige Strategien zusammen und oft auch gegeneinander.
Beginnend von Erstellungsreihenfolge von Objekten (automatisch oder manuell) über Art und Weise von Datenbankzugriff und Problemen mit unterschiedlichen Komponentenversionen.
Ohne mehr Einblick in die Applikation ist es schwer einen Tip zu geben

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von ErnstVolker »

Vielen Dank für Dein Beispielprojekt. Ich bin dabei es mir anzusehen und habe es auch kompiliert bekommen.

Ich generiere das Datenmodul automatisch. Ich kann auch in der Prozedur "DataModuleCreate" als erstes

Code: Alles auswählen

TZConnection.Disconnect;
und anschließend noch

Code: Alles auswählen

TZConnection.Connected:= False;
einfügen. Die Meldung kommt trotzdem.

Ich dachte es gäbe einen "einfachen Weg" eine TZConnection in einer ButtenClick-Prozedur einzuschalten, sozusagen.

Werde mir CharlyTango's Beispiel weiter zu Gemüte führen...

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von charlytango »

Es ist IMHO auch eine Philosophie-Frage.
Wenn man in der GUI Daten in den Controls sehen will, dann muss die DB-Verbindung auch aktiv sein. Da passiert es meistens dass man dann vergisst vor dem Kompilieren die Komponenten auszuschalten und dann kann es Probleme geben.
Das mache ich schon lange nicht mehr. In der GUI ist alles abgeschaltet und dann kann ich mich auf einen definierten Zustand verlassen.

Zum Thema "automatisiertes Erstellen". Auch bei diesem Thema bevorzuge ich mittlerweile Handarbeit und nur mehr das Hauptformular wird automatisch generiert. Alles andere zur Laufzeit erstellt.
Bei umfangreicheren Applikationen stellen sich dann ganz zwangsläufig auch Fragestellungen, wie man die Formulare dann verwaltet oder an die DB anbindet.

Im Beispielprojekt benutze ich ein Datenmodul, denn die Idee für das Projekt war es, anderen ein Framework für Datenbankbeispiele zur Verfügung zu stellen, weil mich immer geärgert hat, dass Beispiele immer für die DB existieren die ich nicht habe. Deswegen auch zum Umschalten.

In meinen Applikationen nutze ich nur "mehr" ein eigenes Zugriffsobjekt das alle Komponenten zur Laufzeit erstellt und benutzt. Diese Strategie habe ich gewählt weil es seit Delphi (und auch Lazarus) Probleme mit der Verterbung von Datenmodulen gibt, bzw ich hatte.

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von ErnstVolker »

Hallo,
ich muß doch nochmal nach der Zeos-Connection fragen.

Ich habe mein Projekt so umgebaut, dass nur noch das Hauptformular automatisch erzeugt wird. Auf diesem befinden sich zwei Textboxen in die der Benutzername und Passwort eingegeben werden. Die Schaltfläche Anmelden erzeugt zunächst das Datenmodul mit der TZConnection, danach die weiteren Formulare die benötigt werden. Die Anmeldung an die Datenbank klappt.

Es funktioniert, solange das Passwort des Benutzers richtig eingegeben wird. Gibt man ein verkehrtes Passwort ein, fliegt man durch den eingebauten try-except-Block raus. Es passiert keine Anmeldung an die DB, auch richtig so. Das ist soweit in Ordnung. Gibt man anschließend das richtige Passwort zum Benutzer ein gibt es trotzdem keine Anmeldung an die DB. Es wird auch der try-Zweig richtig durchlaufen etc.

Schließe ich das Programm, starte es neu, lässt sich mit Benutzer und richtigem Passwort die DB bedienen.

Wie macht man einen "Refresh" oder "Reset" der ZEOS-TZConnection-Komponente?

Schönen Abend und vielen Dank!

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von charlytango »

wie vieles, ist es hier auch eine Designfrage.

Scheinbar willst du aus irgend einem Grund, dass der Benutzer Username und Passwort eingibt, was ich persönlich nur für sinnvoll halte wenn in der DB auch unterschiedliche Aktionen und Berechtigungen pro Benutzer gesetzt werden.

Ich erzeuge das Datenbankobjekt, das die Verbindung zur DB herstellt VOR dem Hauptformular, aber auch das ich Desinsache.

In deinem Fall würde ich das Datenmodul nach dem Hauptformulat erstellen, aber doch ein eigenes Formulat für Username/Passwort verwenden.

Letztlich muss eine Datenverbindung geschlossen sein , um User/Passwort neu zu setzen.

Die Frage ist auch, ob du sicherstellst das dein Algorithmus immer nur ein Datenmodul erzeugt, das die Datenverbindung herstellt.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6763
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von af0815 »

Das Datenmodul als Singleton erstellen, dabei die Connection nicht öffnen. Wenn der User sich verbinden will, so öffnet man die Connetion mit seinen Daten. Öffnet sich die Connection ist alles ok. Meldet er sich neu an, oder Versucht es nach einem Fehlversuch, so schliesse ich immer zuerst die Connection und mache dann einenn neuen Versuch. Achtung, alle offen Queries eerden mit dem reconnect ungültig, das muss man par Design behandeln.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Joh
Lazarusforum e. V.
Beiträge: 280
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von Joh »

Jetzt habe ich doch noch eine blöde Frage zum Datenmodul:
Ein Commit wirkt dann ja global; also als Beispiel:

- Ich erstelle eine Rechnung
- sehe plötzlich, das Artikel 0815 nicht angelegt ist.
- also schnell in das Artikelformular und den Artikel angelegt.
Speichern des Artikels / Commit und ??? Was ist jetzt mit der Rechnung? Die steht plötzlich in der Datenbank obwohl ich sie noch gar nicht Speichern wollte? Oder es gibt einen Fehler beim Speichern des Artikels, weil die Rechnung noch nicht gespeichert werden konnte?


Oder habe ich hier gerade einen Knoten im Hirn?
just my two Beer

Benutzeravatar
gladio
Beiträge: 223
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von gladio »

- Ich erstelle eine Rechnung
- sehe plötzlich, das Artikel 0815 nicht angelegt ist.
- also schnell in das Artikelformular und den Artikel angelegt.
Speichern des Artikels / Commit und ??? Was ist jetzt mit der Rechnung? Die steht plötzlich in der Datenbank obwohl ich sie noch gar nicht Speichern wollte? Oder es gibt einen Fehler beim Speichern des Artikels, weil die Rechnung noch nicht gespeichert werden konnte?
Das hat jetzt weniger mit dem Datamodule zu tun als vielmehr mit deinem Datenhandling.
Wenn du zwischndurch an z.B. der Artikel-Tabelle was aktualisierst (oder Kundendaten,...) und die Aktualisierungen in die Datenbank speicherst, muss der Artikelstamm neu eingelesen werden und die Daten in deiner angefangenen Rechnung aktualisiert werden.
Ob die Rechnung in der Datenbank steht sollte die Entscheidung dessen sein, der eine Rechnung erstellt, heiß bei einer nicht fertige Rechnung muss es die Möglichkeit geben diese wieder zu verwerfen. Eventuell bietet es sich auch an, die Rechnung nicht direkt mit datensensitiven Eingaben zu ertsellen. Also statt DBEdit nur TEdit... usw.
Wenn alles fertig und korrekt ist, mit einem Rutsch in die Datenbank.

Joh
Lazarusforum e. V.
Beiträge: 280
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Datenbank-Zugriff auslagern in Datenmodul

Beitrag von Joh »

So ähnlich hatte ich das befürchtet...
Dann bleibe ich doch lieber bei den formulargebundenen Connections / Transaktionen.
Dann habe ich formularlokale Transaktionen und kann weiter mit den DBObjekten arbeiten.

Solange mit meinen Anwendungen nur max. eine Handvoll Benutzer im LAN arbeiten, sollten die paar Datenbankverbindungen nicht stören.
just my two Beer

Antworten