Firebird und ZEOS

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
FKT
Beiträge: 5
Registriert: Di 19. Apr 2016, 19:10
OS, Lazarus, FPC: Win10 (L 1.6.51630 / FPC 3.0.)
CPU-Target: 64Bit

Firebird und ZEOS

Beitrag von FKT »

Hallo,
nach einigen Jahren Pause versuche ich mich seit kurzem wieder mit der Programmierung von Anwendungen. Nach Clipper, TurboPascal und Delphi bin ich jetzt bei LAZARUS Ver. 1.6.51630 / FPC: 3.0.0 angekommen. Neu ist auch die Datenbank mit der ich jetzt arbeite, nämlich Firebird (Embedded Vers.: 2.5) und die passenden ZEOS Komponenten (Ver. 7.1.4-stable). Und hier liegt im Moment mein Problem. Ich habe bisher keine Erfahrungen mit SQL.

Ich habe eine kleine Datenbank zur Benutzerverwaltung (als Teil einer größeren Anwendung) angelegt (mit Firebird Maestro - Testversion). Die Tabelle hat einen Primärindex und zwei weitere Indices. Alle Felder sind CHAR, bzw. Integer. Beim Öffnen der UNIT werden ausgewählte Felder aller Datensätze in einem DBGrid angezeigt (PageControl/TabSheet 1). Der aktuell ausgewählte Datensatz wird detailliert in PageControl/TabSheet 2 angezeigt. Die Bearbeitung der Daten erfolgt ausschließlich in der Einzelanzeige, nicht im DBGrid. Der Primärindex (laufende Nr.) wird über einen Trigger und den passenden Generator mit Daten versorgt. Das Anlegen, Ändern und Löschen von Datensätzen funktioniert. Allerdings gibt es ein Problem wenn ich einen Datensatz neu anlege, abspeichere und diesen neu angelegten Datensatz ändern will. Das Programm steigt mit einer Fehlermeldung aus (Bild1). Schließe und öffne ich dann die UNIT erneut kann ich die Änderungen durchführen.

Leider hat meine Suche in div. Foren und Anleitungen zu keinem Ergebnis geführt. Vielleicht kann mir jemand aus dem Forum auf die Sprünge helfen. Ich bin für jede Hilfe dankbar.

Friedrich


Folgende Komponenten werden verwendet:

C1 = TZConnection1
Q1 = TZQuery1
DS1 = DataSet1

Die Einstellungen habe ich als Bilder angehängt.

Hier der Code (nicht vollständig):

procedure TDPBen.FormCreate(Sender: TObject);
begin

// -------------------- TZQuery und TZConnect einrichten ----------------
DS1.DataSet := Q1;
Q1.Close;
Q1.SQL.Clear;
Q1.SQL.Text := 'select * from BENUTZERVERWALTUNG';
Q1.IndexFieldNames := 'Sortiername Asc';
Q1.Connection := C1;
C1.AutoCommit := False;
C1.Database := 'F:\....\TES\Daten\DATA.FDB';
C1.User := 'SYSDBA';
C1.Password := 'masterkey';
Q1.Active := True;
Q1.Open;
C1.Connected := True;

/-------------------------------------------------------------------------
// 2. Datenbearbeitung
//-------------------------------------------------------------------------
// 2.1. Vorbereitung für Neueingaben und Änderungen
//-------------------------------------------------------------------------
procedure TDPBen.NeuUndBearbeiten;
begin
if Neu = 'ja' then // = neuer Datensatz
begin
DS1.DataSet.Append; // Datensatz anhängen
Q1.FieldValues['Master'] := 0; // Feld "Admin" vorbelegen
Q1.FieldValues['Aendern'] := 0; // Feld "Ändern" vorbelegen
Q1.FieldValues['Drucken'] := 0; // Feld "Drucken" vorbelegen
Q1.FieldValues['ExtPrg'] := 0; // Feld "ExtPrg" vorbelegen
end
else // Datenänderung
begin
DS1.DataSet.Edit; // Datensatz ändern
end;
end;

//-------------------------------------------------------------------------
// 4.4. neuen / geänderten Datensatz speichern
//-------------------------------------------------------------------------
procedure TDPBen.DBSavClick(Sender: TObject);
begin
DS1.DataSet.Post; // Eingabe/Änderung abschl.
Q1.ApplyUpdates;
C1.Commit;
BearbeitenModusVerlassen;
end;

//-------------------------------------------------------------------------
// 3.2.2. Formular schließen
//-------------------------------------------------------------------------
procedure TDPBen.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
Q1.close; // Datentabelle schließen
C1.Connected := false; // Verbindung schließen
end;
Dateianhänge
Bild4.jpg
Bild3.jpg
Bild2.jpg
Bild1.jpg
Bild1.jpg (23.22 KiB) 1400 mal betrachtet

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Firebird und ZEOS

Beitrag von Michl »

Zur Zeit nutze ich Zeos 7.2 Trunk. Meine Vermutung war, dass die Änderungen nicht richtig erkannt werden, allerdings schaffe ich es nicht einen derartigen Fehler nachzustellen. Wenn du willst, kannst du das Projekt (möglichst minimiert) hier hochladen (nur die Source-Dateien *.lpi *.lpr *.lfm *.pas *.inc *.pp in einem Zip) und ich teste dein Projekt in einer Dummy-Datenbank gegen. Allerdings habe ich zur Zeit nur PostgreSQL installiert, sollte, falls es ein logisches Problem ist, aber auch dort nachzustellen sein. Falls du das so machen willst, gib bitte nochmal genau die Schritte an, die zum Error führen.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

FKT
Beiträge: 5
Registriert: Di 19. Apr 2016, 19:10
OS, Lazarus, FPC: Win10 (L 1.6.51630 / FPC 3.0.)
CPU-Target: 64Bit

Re: Firebird und ZEOS

Beitrag von FKT »

Hallo Michl,

danke für deine Unterstützung. Ich habe das Ganze mal vereinfacht und in eine ZIP-Datei gepackt. Der Fehler entsteht nach Eingabe eines neuen Datensatzes (Name und Vorname genügt). Dann mit Button "Speichern" abspeichern. Jetzt den neu angelegten Datensatz aus dem Grid auswählen. Mit dem Button "Ändern" in die Einzelansicht wechseln, den Vornamen oder Namen ändern und wieder mit dem Button "Speichern" abspeichern. Danach gibt's bei mir die Fehlermeldung.

Noch eine Frage zu den Versionen von Firebird und ZEOS: Ist es ratsam, jetzt (bevor ich im Projekt groß weiterarbeite) auf die neuen Versionen umzusteigen (natürlich erst, wenn der Fehler gefunden ist)?

Friedrich
Dateianhänge
TES_Code.zip
(579.35 KiB) 52-mal heruntergeladen

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6209
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: Firebird und ZEOS

Beitrag von af0815 »

BTW.Man kann auf demselben Rechner verschiedene Version laufen lassen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Firebird und ZEOS

Beitrag von Michl »

FKT hat geschrieben:Der Fehler entsteht nach Eingabe eines neuen Datensatzes (Name und Vorname genügt). Dann mit Button "Speichern" abspeichern. Jetzt den neu angelegten Datensatz aus dem Grid auswählen. Mit dem Button "Ändern" in die Einzelansicht wechseln, den Vornamen oder Namen ändern und wieder mit dem Button "Speichern" abspeichern. Danach gibt's bei mir die Fehlermeldung.
Habe das Projekt bei mir mit einer Dummydatenbank getestet. Bei mir gibt es keine Probleme. Habe nichts an der Logik geändert.

Daher würde ich dir als nächsten Schritt den Test mit einem neueren ZEOS empfehlen (gibt es als Trunk, 7.2 beta, 7.3 alpha). Die 7.2 beta ist eigentlich ausgereift und wird wahrscheinlich nicht mehr lange als stabil auf sich warten lassen.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

FKT
Beiträge: 5
Registriert: Di 19. Apr 2016, 19:10
OS, Lazarus, FPC: Win10 (L 1.6.51630 / FPC 3.0.)
CPU-Target: 64Bit

Re: Firebird und ZEOS

Beitrag von FKT »

Hallo Michl,
danke für die Info. Wenn das Wetter es zulässt, werde ich Deinen Vorschlag mal über die Feiertage testen und das Ergebnis hier einstellen.

Friedrich

FKT
Beiträge: 5
Registriert: Di 19. Apr 2016, 19:10
OS, Lazarus, FPC: Win10 (L 1.6.51630 / FPC 3.0.)
CPU-Target: 64Bit

Re: Firebird und ZEOS

Beitrag von FKT »

Hallo Michl,

ich konnte das Problem eingrenzen. Die Eingabe und anschließende Änderung funktioniert einwandfrei, wenn ich die zugrundeliegende Tabelle ohne Primärindex anlege/aufrufe. Wird sie mit Primärindex geöffnet, erscheint der Fehler, auch mit den neuen ZEOS-Komponenten. Offensichtlich liegt der Fehler nicht an den Komponenten oder der Programmierung, sondern am Primärindex der Datenbank. Werde hier noch mal genauer nachsehen, ob ich dazu etwas finde. Falls Du eine Idee dazu hast, könntest Du mir vielleicht eine kurze Info zukommen lassen. Danke.

Friedrich

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6209
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: Firebird und ZEOS

Beitrag von af0815 »

Die Fehlermeldung kommt IMHO dann, wenn der Server erkennt das mehr als eine Reihe upgedated werden soll. Schaut so aus als würde der Primärindex nicht oder nicht richtig zugeordnet werden. Wenn du keinen definierst, so wird oft ein automatischer Index zur Laufzeit erzeugt, deswegen geht es ohne Index. Das Problem besteht sicher schon beim öffnen der DB, wenn du eine Änderung machst und der Index ist nicht eindeutig, so gibt es die Meldung vom Server beim Update, Delete oder Insert.

Ich habe mir das nicht angesehen, aber es fällt mir noch dazu ein - Views und Joins machen genauso die Probleme, wenn nicht eindeutig ist, welche Tabelle betroffen ist und der PK nicht eindeutig zu identifizieren.

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Firebird und ZEOS

Beitrag von Michl »

Eigentlich hat Andreas schon das Wichtigste gesagt, möchte dies aber noch unterstreichen.
FKT hat geschrieben:Die Eingabe und anschließende Änderung funktioniert einwandfrei, wenn ich die zugrundeliegende Tabelle ohne Primärindex anlege/aufrufe. Wird sie mit Primärindex geöffnet, erscheint der Fehler
Das hatte ich tatsächlich aus Macht der Gewohnheit in meiner Dummy-Datenbank anders gemacht. Ich erstelle eigentlich fast immer Tabellen mit einem Primärschlüssel. Ohne diesem sollten, wie Andreas schrieb, diverse Methoden der Datenbankkomponenten nicht funktionieren. Einzige Ausnahmen sind manchmal Hilfstabellen, die ich mit Joins verbinde. Da nützen mir die Datenbankkomponenten aber sowieso nichts und Datensätze müssen zu Fuß eingepflegt / geändert / gelöscht werden.
Um Probleme zu vermeiden, wenn z.B. Namen doppelt vorhanden sein können, würde ich immer empfehlen einen (autoincrement) Primärschlüssel zu verwenden.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6209
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: Firebird und ZEOS

Beitrag von af0815 »

Ich habe mal in den Code hineingesehen, das wird IMHO eine Serverdatenbank wie eine Desktopdatenbank verwendet.

Mach mal das SQL-Statement besser verstehbar (für Mensch UND Server)

Code: Alles auswählen

SELECT Name,Vorname,User,Master,Aendern,Drucken, ExtPrg FROM mytable ORDER BY Name ASC


Das sind vermutlich die Felder die du haben willst. Weiters lass mal IndexFieldNames weg, es ist besser Sortierungen mit echten SQL-Statements zu machen.

Wird das AutoCommit aus einem speziellen Grund von dir dezidiert deaktiviert - willst du die Transaktionen händisch verwalten ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

FKT
Beiträge: 5
Registriert: Di 19. Apr 2016, 19:10
OS, Lazarus, FPC: Win10 (L 1.6.51630 / FPC 3.0.)
CPU-Target: 64Bit

Re: Firebird und ZEOS

Beitrag von FKT »

Hallo Michl,
hallo Andreas,

danke für eure Hinweise. Ich habe eine kleine Tabelle mit drei Feldern erstellt (ID = autoinc, NOTNULL, integer für Primärindex und 2 CHAR-Felder), dazu den Standard dbNavigator. Bei Eingabe eines neuen Datensatzes werden die CHAR-Felder gefüllt und der Datensatz abgespeichert. Obwohl ich in der DB einen Trigger und einen Generator für den Unique-Key (ID) erstellt habe (BeforeInsert), wird das Feld nach einem post nicht mit Generator-Wert belegt. Wenn ich nach dem post einen refresh mache, wird der Wert aus dem Generator übernommen. Das ist wohl der Grund, warum direkte Änderungen nach einer Neuanlage - ohne refresh - nicht funktionieren. Muss ich hier zusätzlich zur Trigger und Generator-Automatik in der DB noch etwas unternehmen, um den generierten Wert bei einem post dem neuen Datensatz zuzuordnen?
Ähnliches passiert, wenn ich statt der ZEOS- die dbsql-Komponenten nehme. Nach dem post erscheint die Fehlermeldung, dass das ID-Feld leer ist und der Vorgang wird abgebrochen.

Friedrich

Antworten