[gelöst] Datasource / SQLQuery zu eng verbunden???

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
alfware17
Beiträge: 134
Registriert: Di 14. Dez 2010, 23:27

[gelöst] Datasource / SQLQuery zu eng verbunden???

Beitrag von alfware17 »

Hallo,

ich habe in einer Form ein Datagrid und eine Datasource, letztere kriegt als Dataset zugewiesen eine SQLQuery1 aus einer Unit (eigenes Objekt),
wo meine ganzen Datenbank-Abfragen drin sind (die Unit soll auch im Batch arbeiten später, hier ist auch die Connection und die Transcation).

Es wird auch angezeigt, allerdings gibt es ein merkwürdiges Verhalten. Sobald ich die SQLQuery1 verändere (andere Abfragen in meiner Datenbank-Unit,
die mit dem Datagrid auch nichts zu tun haben sollen), ändert sich trotzdem auch die Anzeige des Datagrids.
Obwohl ich keine erneute Zuweisung gemacht habe, also wie bspw. beim Sortieren.
Wo ist die Verbindung? Und wie kann ich das verhindern. Irgendwie habe ich da einen Knoten im Gehirn, sorry ja ich weiss. aber es ist mein erstes SQLite
Projekt bei Lazarus.

Ich habe dem Datasource schon schrittweise eine zweite SQLQuery2 spendiert (da maulte die Transaction), auch zweite Transaction und zuletzt eine zweite
Connection. Außer Exceptions zur Laufzeit kein Erfolg. Sehr stutzig machte mich aber, daß selbst wenn ich mit Connection2, Transaction2 und SQLQuery2
die Fehlermeldung im Debugger dann übergehe, die Anzeige im Grid sich doch noch ändert!!!

Das Projekt als Source kann ich anhängen, falls erforderlich.

Und noch mal in einem Satz: Ich möchte gerne meine SQLQuery trotzdem weiter verwenden/verändern können, ohne daß das Datagrid gleich Änderungen
zeigt (erst wieder, wenn ich es halt zulasse)

Danke
Zuletzt geändert von alfware17 am Do 30. Nov 2017, 17:41, insgesamt 1-mal geändert.

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

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von gladio »

Dein DBGrid ist über die Datasource mit der Query verbunden (genau diese Reihenfolge).
Sobald du in der Query die Abfrage änderst und damit das Abfrageergebis , wird dies über die Datasource an das Grid weitergegeben.
Es ist also das normale Verhalten was du da beschreibst.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von Socke »

In diesem Fall musst du alles, was nicht angezeigt werden soll, in einer separten SQL-Query durchführen. Du kannst diese separate SQL-Query dann natürlich später zur Anzeige nutzen, indem du sie mit der DataSource verbindest.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

alfware17
Beiträge: 134
Registriert: Di 14. Dez 2010, 23:27

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von alfware17 »

Hallo Socke,

habe ich ja probiert... habe 1 Connection, 3 Transactions, 3 SQLQuerys (eine für normale Abfragen, eine für den Dataset und eine noch eine Liste, die ich eventuell auch parallel benutzen wollte).
Das Problem nur, dann sagt mir SQlite "kann nicht eine Transaktion in einer anderen Transaktion starten" (der Dataset ist offen, ein anderes Select löst dann die Exception aus).
Habe die auch vorsorglich committed (wenn SQLQuery 1 startet, 2 und 3 zu machen) - aber das Committen schließt dann auch den Dataset.

Ich wollte von der Anwendung her eigentlich nur folgendes machen. Das DBGrid (also Liste/SqlQuery3) zur Auswahl, auf Doppelklick hole ich mir den Key und mache modal ein Update-Fenster auf,
welches natürlich :mrgreen: über SqlQuery 1 noch mal den einen Satz lesen soll, ggf. auch update, insert oder einfach weitere Selects.

Klar kann ich nach dem Schließen des Update-Fensters den SqlQuery für den DbGrid noch einmal lesen, aber selbst während dem Arbeit auf dem modalen Fenster verändert sich das Grid des Haupfensters,
und das ist ja unschön.

In Java/C# läuft eine ähnliche Anwendung (auch mit SQLite) tadellos, allerdings ist da das entsprechende JTable/Datagrid/Datasource usw. nicht auf meinem Mist gewachsen, die habe ich so hingenommen.
Deswegen frage ich mich, man müßte doch das Datasource irgendwie schlafen legen / einfrieren können? Jedenfalls solange bis ich wieder Refresh sage oder so?

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

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von gladio »

Hast du denn für jede Query eine eigene Datasource?

Ich habe schon ewig nicht mit Transactionen gearbeitet. Vermutlich genügt aber auch eine.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von mse »

alfware17 hat geschrieben:Ich wollte von der Anwendung her eigentlich nur folgendes machen. Das DBGrid (also Liste/SqlQuery3) zur Auswahl, auf Doppelklick hole ich mir den Key und mache modal ein Update-Fenster auf,
welches natürlich :mrgreen: über SqlQuery 1 noch mal den einen Satz lesen soll, ggf. auch update, insert oder einfach weitere Selects.

In SQLite3 empfiehlt es sich mit impliziten Transaktionen zu arbeiten, da SQLite3 keine parallelen Transaktionen kennt. Implizite Transaktion heisst, dass bei jedem Statement in der DB automatisch eine Transaktion geöffnet und geschlossen wird. In MSEgui und Zeos ist das die Grundeinstellung, IIRC hat mittlerweile auch FCL-Sqldb eine entsprechende Einstellung.
Es ist auch zu beachten, dass eine nicht abgeschlossene Leseoperation Schreiboperationen auf dieselbe DB in anderen Anwendungen blockiert. Wird in der IDE eine Query geöffnet, der Lesevorgang wegen der TSQLQuery.PacketRecords Einstellung nicht abgeschlossen, kann die gestartete Anwendung nicht schreiben. Der Wert von "Packetrecords" sollte daher -1 sein.
Habe die auch vorsorglich committed (wenn SQLQuery 1 startet, 2 und 3 zu machen) - aber das Committen schließt dann auch den Dataset.

Dazu gibt es AFAIK eine Einstellung welche die Datasets nach committen nicht schliesst. In MSEgui ist es TmseSQLTransaction.Options tao_fake oder auch TmseSQLQuery.Options bdo_offline.
Klar kann ich nach dem Schließen des Update-Fensters den SqlQuery für den DbGrid noch einmal lesen, aber selbst während dem Arbeit auf dem modalen Fenster verändert sich das Grid des Haupfensters,
und das ist ja unschön.
Deswegen frage ich mich, man müßte doch das Datasource irgendwie schlafen legen / einfrieren können? Jedenfalls solange bis ich wieder Refresh sage oder so?

TDataset.DisableControls()/EnableControls() legt die Datalinks still. Allerdings werden dann auch die DB-Controls im modalen Fenster nicht Arbeiten.
In MSEgui kann man auf die Datensätze wahlfrei zugreifen ohne den Datensatzcursor zu verschieben, diese Möglichkeit bieten FCL-SQLdb und Zeos AFAIK nicht.
Zuletzt geändert von mse am Do 30. Nov 2017, 10:07, insgesamt 1-mal geändert.

charlytango
Beiträge: 842
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: Datasource / SQLQuery zu eng verbunden???

Beitrag von charlytango »

Hi
alfware17 hat geschrieben:Deswegen frage ich mich, man müßte doch das Datasource irgendwie schlafen legen / einfrieren können? Jedenfalls solange bis ich wieder Refresh sage oder so?


Natürlich kannst (und sollst) du die Aktualisierung der Controls die (über ein TDatasource) an an einem Dataset hängen unterbinden:

Code: Alles auswählen

MyDataset.DisableControls;

zu finden hier: http://lazarus-ccr.sourceforge.net/docs/fcl/db/tdataset.disablecontrols.html

Zum Thema Transactions: Das wovon du schreibst heißt "Nested Transactions" - also eine Transaktion innerhalb einer anderen.
SQLite scheint das tatsächlich zu beherrschen -> https://sqlite.org/lang_transaction.html.
Ob das in den Lazarus komponenten implementiert ist, weiß ich aus der Hüfte nicht.

Trotzdem frage ich einfach mal nach warum du das tun willst? Deine Anforderungen aus einem DBGrid ein modales Fenster zum Editieren der Daten zu öffnen macht das nicht nötig -- eine einzige Transaktion wäre völlig ausreichend.


Ja nachdem welches Programmdesign du bevorzugst nur einige Varianten:

Variante 1
spendiere dem Editierfenster ein eigenes TSQLQuery und ein eigenes TDatasource an das du die Controls hängst.

Variante 2
das eigene TSQLQuery und TDatasource des Editierfensters liegt in einem eigenen Datenmodul.
Das kannst du wie folgt erzeugen: Menü-> Datei->Neu->Datenmodul

Variante 3
Wenn es dir lieber ist, alle Datenkomponenten zusammen zu halten, dann eben nur ein TDatasource auf dem Formular.
Achte darauf dass das Formular ein eigenes TSQLQuery aus deiner Auswahl und der Grid ein anderesbenutzt.

Wenn das so getrennt ist, hast du keine Probleme mit kreuzweiser Aktualisierung der Daten - im Gegenzug handelst du dir die manuelle Aktualisierung des Grids ein. TSQLQuery.Refresh wäre da mal eine Möglichkeit. Die Positionierung des Datensatzzeigers (und damit die position im DBGrid) musst du extra behandeln.

Variante 4
Du benutzt für DBGrid und Editierfenster die selbe TDatasource. dann musst du dafür sorgen dass die Anzeigeaktualisierung des DBGrid jeweils ein und ausgeschaltet wird.

alfware17
Beiträge: 134
Registriert: Di 14. Dez 2010, 23:27

Re: Datasource / SQLQuery zu eng verbunden???

Beitrag von alfware17 »

Jippie :D es läuft 8)

mse und charlytango, danke für eure prompte Hilfe und die vielen Tips, die ich bei Gelegenheit auch mal als Varianten prüfen werde.

Im Projekt habe ich jetzt 1 Connection, 1 Transaction und 3 SqlQueries.

Warum 3? Nunja die erste macht meine "normalen" SQLs, die zweite bedient Datasource.Dataset also das DBGrid und nunja die
dritte braucht mein modales Fenster, wenn es böse ist und neben SQLs auch noch eine Liste meiner Objekte aufruft
(ähnlich wie das für Dataset nur eben als generische Liste, und da hatte ich dummerweise auch die zweite SqlQuery dafür benutzt).

Mit disable/enableControls ließ sich dieser Fehler sogar verdecken, ich fand es erst, als ich das wegließ (geht also jetzt auch ohne),

Und noch eine weitere Boshaftigkeit meines modalen Update-Fensters deckte das Weglassen des disable/enableControls auf -
das Fenster hatte nämlich als Baustelle schon mal Aufrufe der Insert/Update/Delete Methoden meines Datenbank-Objektes gerufen
und dummerweise machen die Commit auf die einzige Transaction, jetzt verstehe ich es auch. Dann sind die Dataset-Daten deswegen weg,
Aber ok das kriege ich durch Aufruf in der Main-Form einfach hin, da soll es eigentlich auch hin, ich war nur noch nicht so weit vom Design.

Nebenbei habe ich durch Googlen jetzt auch verstanden, daß mein Dataset also über die SqlQuery2 sogar ein "Update where current" anstoßen
könnte, wenn ich das Dataset nicht readonly halte, sondern Veränderungen zulasse und dann Post und ApplyUpdates aufrufe, aber das will
ich hier nicht, vielleicht ein anderes Mal. Nur ist das für mich auch die Erklärung, warum (naja also siehe meine Post-Überschrift) :mrgreen:

Antworten