Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Änderungen an DateTimePicker wird eine ADO Exception (https://www.delphipraxis.net/182726-aenderungen-datetimepicker-wird-eine-ado-exception.html)

michele_tedesco 13. Nov 2014 11:16

Änderungen an DateTimePicker wird eine ADO Exception
 
Wenn ich in einem TDateTimePicker, welches soeben als neue Zeile einer DBGrid hinzugefügt worde ist (ADO mit SQL DB), das Datum ändere, erhalte ich eine EOleException und eine EDatabaseError exception.
Diese verhalten ist nicht 100% nachvollziehbar, manchmals funktioniert der Update problemlos.

Hier der Code-snippet:
Delphi-Quellcode:
IF AdoTask.Active THEN BEGIN
        IF AdoTask.State <> dsEdit THEN
          AdoTask.Edit
        ELSE
          Changing := TRUE;
        if EditTerminTime.Checked then
          AdoTask.FieldByName('TaskTermin').AsDateTime := StrToDateTime(DateToStr(EditTerminDate.Date)+' '+TimeToStr(EditTerminTime.Time))
        else
          AdoTask.FieldByName('TaskTermin').AsDateTime := EditTerminDate.Date;
        AdoTask.Post;
      END; (* if *)
Die Exception sagt: Row cannot be located for updating. Some values may have been changed since it was last read
Oder auf Deutsch: die zum aktualisieren angegebene zeile wurde nicht gefunden: einige werte wurden seit dem letzten lesen geändert

Was mache ich falsch?
Was habe ich übersehen?

Gruss und Danke

himitsu 13. Nov 2014 11:34

AW: Änderungen an DateTimePicker wird eine ADO Exception
 
Das Updatestatement lässt du automatisch erstellen? (verlutlich ja ... du gibts doch bestimmt nur ein SELECT an)
Sucht sich die Querkomponente selber ein ID-Feld, oder gibt du es explizit an? (Letzeres vermutlich nicht)
Wurde der Datensatz datenbankseitig zwischenzeitlich verändert? (z.B. in einem Trigger oder durch wen Anderes)
Bei datenbankseitigen Änderungen (Trigger), werden diese Änderungen geladen? (RefreshAfterPost oder so)

michele_tedesco 14. Nov 2014 10:52

AW: Änderungen an DateTimePicker wird eine ADO Exception
 
Danke fürs Feedback.

Ich habe folgendes festgestellt:
Das DBGrid beinhaltet 6 Felder, eins davon ist ein Datumfeld.
Das Abfüllen dieser Spalte passiert anhand zwei TDateTimePicker.
Eines für das Datum und eines (mit aktivierter Checkbox) für die Zeit.
beim OnExit Event beider DateTimePicker wird geprüft ob die Time-Checkbox aktiv ist und je nachdem nur das Datum oder Datum und Uhrzeit gespeichert (mit einem Ado.Edit --> Ado.Post).

Delphi-Quellcode:
procedure TForm3.DateTimePicker2Exit(Sender: TObject);
var
  Checked : Boolean;
  aDate : TDateTime;
  aTime : TDateTime;
begin
  Checked := DateTimePicker2.Checked;
  aDate := DateTimePicker1.Date;
  aTime := DateTimePicker2.Time;
  if ADOQuery1.Active then begin
    ADOQuery1.Edit;
  end;
  if Checked then
    ADOQuery1.FieldByName('TaskTermin').AsDateTime := StrToDateTime(DateToStr(aDate)+' '+TimeToStr(aTime))
  else
    ADOQuery1.FieldByName('TaskTermin').AsDateTime := aDate;
  ADOQuery1.Post;
end;
Wenn ich das AdoQuery-Feld NICHT abfülle mit den DateTimePicker-Werte, dann erhalte ich die Fehlermeldung NIE!
Sobald ich aber der AdoQuery-Feld abfülle erhalte ich diese ( :evil: ) Fehlermeldung.

Gibt es bekannte Probleme in Kombination mit dem TDateTimePicker und ADO-Queries?

Danke nochmals.

haentschman 14. Nov 2014 11:38

AW: Änderungen an DateTimePicker wird eine ADO Exception
 
Moin...

ADO macht beim Update eines Datensatzes intern ein Locate um den alten zu "identifizieren". Das Locate funktioniert bei ADO über einen Filter. Ist nach der Filterung ein Datensatz vorhanden ist er "located" wenn das Ergebnis leer ist nicht.

Ich hatte den Fehler in Verbindung mit einem ClientDataset. Ob das die Ursache war ist noch nicht bekannt. Jedenfalls hat der interne "Locatefilter" immer mit Millisekunden = 000 gearbeitet. da in der DB, in diesem Falle, 815 drin stand schlug das Update fehl. Stelle mal sicher daß die Millisekunden im Datetime Wert immer = 000 ist. Was konkret die Auswahl am DatetimePicker an Millisekunden liefert ist mir jetzt nicht bekannt.

Vieleicht hilft´s ja. :P

michele_tedesco 14. Nov 2014 13:14

AW: Änderungen an DateTimePicker wird eine ADO Exception
 
VIELEN DANK haentschman !!!

Ich habe zwar dass Problem noch nicht gelöst, jedoch kann ich nun 100% nachvollziehen, dass bei einer SEKUNDEN-Änderung nach dem AdoQuery.POST die Änderung nicht gespeichert wird.
Ändere ich die Minuten oder die Stunden funktioniert das wunderbar. Nur die Sekunden werden aus irgend einem Grund nicht gespeichert.

Millisekunden werden in der DB nicht gespeichert.

Danke nochamls!

Dejan Vu 14. Nov 2014 16:32

AW: Änderungen an DateTimePicker wird eine ADO Exception
 
Delphi-Quellcode:
// Wieso so:
ADOQuery1.FieldByName('TaskTermin').AsDateTime := StrToDateTime(DateToStr(aDate)+' '+TimeToStr(aTime))
//
// und nicht so: ? 
ADOQuery1.FieldByName('TaskTermin').AsDateTime := aDate + aTime; // Oder -um sicher zu gehen : ' + trunc(aTime)
Zum Thema:
ADO macht einen auf den ersten blick sehr merkwürdigen Befehl zum ändern eines Datensatzes.
Code:
UPDATE Tabelle
   Set Feld = <NeuerWert>
  Where Feld = AlterWert
    and Feld1 = AlterWert1
    and Feld2 = AlterWert2
    and Feld3 = AlterWert3
...
    and FeldN = AlterWertN
Es wäre nun denkbar (weil z.B. Zeitwerte ja als Float abgelegt sind), das einer der Vergleiche nicht mehr hinhaut. Dann wird gar kein Datensatz verändert. ADO prüft den Rückgabewert, der normalerweise aussieht wie '1 Row(s) updated'. Hier kommt aber '0 Row(s) updated' zurück und daher die Fehlermeldung. Die alten Werte hat sich dein ADO geholt, als die Tabelle geladen wurde. In der Zwischenzeit könnte jemand anderes diesen Datensatz verändert haben und dann haut eben diese Abfrage nicht hin. Beispiel: Du lädst den Datensatz mit den Werte (1,2,3). Jemand anders ändert die 3 auf 4.
Nun kommt dein UPDATE-Befehl: 'Ändere im Datensatz (1,2,3) den Wert '3' auf '5'.... Nun gibt es diesen Datensatz ja nicht mehr (der heißt ja nun (1,2,4))...

ADO wird alle Felder in der 'WHERE'-Klausel aufführen, die in ihren ProviderFlags den Wert 'pfInWhere' gesetzt haben. Ich hoffe, deine Tabelle hat einen Primärschlüssel. Versuche also Folgendes: Lösche bei allen Feldern außer dem Primärschlüssel den Wert 'pfInWhere'. Setze 'pfInWhere' nur im Primärschlüsselfeld.

Das sollte den Provider dazu bringen, den UPDATE-Befehl so zu ändern, wie man ihn erwartet:
Code:
UPDATE Tabelle
   SET Feld = NeuerWert
 WHERE PKFeld = Schlüssel
Damit wird der Datensatz immer gefunden und man erlebt keine Überraschungen. Vor allen Dingen bei 'Float'-Feldern, also Feldern mit Fließkommazahlen, knallt es hier immer wieder.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz