AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi TQuery (BDE) / TDataSet - Verständnisproblem "Modified"
Thema durchsuchen
Ansicht
Themen-Optionen

TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

Offene Frage von "Uwe Raabe"
Ein Thema von Bodenseematze · begonnen am 26. Aug 2024 · letzter Beitrag vom 29. Aug 2024
Antwort Antwort
Seite 1 von 2  1 2      
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#1

TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 11:51
Hallo zusammen,

ich weiß: BDE ist alter Tobak und sollte ersetzt werden, genau wie das von mir verwendete Delphi 7...
...aber ich muss es halt aktuell (noch) verwenden
(und außerdem bin ich nicht sicher, ob es nicht bei anderen TDataSet-Klassen auch so ist)

Vielleicht kann mir trotzdem noch jemand aus seiner Erfahrung berichten - ich verstehe nämlich nicht so ganz, wie ich erkenne, ob sich ein Datensatz geändert hat oder nicht...

Hier kurz meine Problemschilderung:
Ich versuche in meinen datenbankbasierten Masken anzuzeigen, ob sich der aktuell aufgeschaltete Datensatz geändert hat (d.h. ob eine der Datenbankfelder auf der Maske sich verändert haben oder ob der gesamte Datensatz neu ist).

Die Datenbankverbindung ist zu einem MS-SQL Server über einen ODBC-Eintrag gemacht - es wird in der BDE entsprechend die ODBC-DSN verwendet.
Auf der Maske ist ein TQuery mit CachedUpdates=True, UpdateMode=upWhereKeyOnly und UpdateObject gesetzt (Rest der Properties sind "false") und das dazugehörige TDataSource, dass sich auf die Query als DataSet bezieht; alle auf der Maske befindlichen Edit-Felder beziehen sich auf diese TDataSource und ein DataField aus dem TQuery.

Um zu prüfen, ob Änderungen im Query sind, wird in einer allgemeinen Methode "HasChanges" folgendes geprüft:
Delphi-Quellcode:
Result := false;
if ( qry.Active and qry_.CanModify ) then begin
  if ( (qry_.State = dsEdit) or (qry_.State = dsInsert) ) then begin
    Result := true;
  end
  else
  if ( qry_.CachedUpdates and qry_.UpdatesPending ) then begin
    Result := true;
  end;
end;
Wenn ich jetzt direkt nach dem Öffnen des Queries mit einem (!) Datensatz die Prüfmethode aufrufe, kommt "true" (d.h. es gibt Änderungen) zurück.
Wenn ich mir das Query genauer anschaue, sehe ich folgendes:
Active=true, CanModify=true, RecordCount=1, UpdateStatus()=Modified, State=dsBrowse, CachedUpdates=true, UpdatesPending=true
Und wenn ich über alle Fields in dem Datensatz laufe und mir diese anschaue, sehe ich keinerlei Änderungen (Value, NewValue, ggf. OldValue sind alle gleich).

Wieso wird mir als "UpdateStatus()" Modified zurückgeliefert?
Und warum ist "UpdatesPending" gesetzt?
Und das direkt in "AfterScroll"!?

Ich glaube, ich verstehe die Properties sowie die Methode "UpdateStatus()" nicht so richtig...
...kann mir da jemand Licht ins Dunkel bringen?

Geändert von Bodenseematze (26. Aug 2024 um 12:00 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#2

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 12:12
Status steht auf Browse, nicht auf dsEdit oder dsInsert ... OldValue und NewValue können somit garnicht unterschiedlich sein.

Nja, es liegt ja eh am UpdatesPending=True.
Du hast also "wartende" Änderungen? Und somit stimmt des True.
Frag mich aber nicht, wie man ins ÄnderungsLog, bzw. in die Änderungsliste (wartende Update) reinschaut. Keine Ahnung.

qry_.UpdatesPending kann eigentlich nur True sein, wenn qry_.CachedUpdates es auch ist, womit man die eine Prüfung weglassen können dürfte.


if qry_.State in [dsEdit, dsInsert] then begin

Delphi-Quellcode:
Result := ( qry.Active and qry_.CanModify )
      and ( (qry_.State in [dsEdit, dsInsert]) or qry_.UpdatesPending );
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#3

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 13:15
Nja, es liegt ja eh am UpdatesPending=True.
Du hast also "wartende" Änderungen? Und somit stimmt des True.
Was sind denn dann "wartende" Änderungen?
Ich bin mir nicht bewußt, dass sowas vorliegt..

Frag mich aber nicht, wie man ins ÄnderungsLog, bzw. in die Änderungsliste (wartende Update) reinschaut. Keine Ahnung.
Das wäre in dem Fall schon interessant...

qry_.UpdatesPending kann eigentlich nur True sein, wenn qry_.CachedUpdates es auch ist, womit man die eine Prüfung weglassen können dürfte.
Hmm, eigentlich ist so ein blödes Wort - eigentlich sollte ich auch keine "wartenden" Änderungen haben...
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#4

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 14:18
UpdatesPending ist True, wenn Records (nicht zwingend der aktuelle Record!) verändert, hinzugefügt oder gelöscht wurden, und es kommt nur bei aktivem CachedUpdates vor. Deswegen geht es nach einem ApplyUpdates bzw. CommitUpdates wieder weg.

Der Status des aktuellen Records wird in Modified geführt. Es kann aber sein, dass noch nicht alle Änderungen in den datensensitiven Controls berücksichtig wurden. In dem Fall genügt ein Aufruf von UpdateRecord um das zu aktualisieren. Das ist übrigens bei allen DataSets so und hat nichts mit der BDE zu tun.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#5

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 15:56
UpdatesPending ist True, wenn Records (nicht zwingend der aktuelle Record!) verändert, hinzugefügt oder gelöscht wurden, und es kommt nur bei aktivem CachedUpdates vor. Deswegen geht es nach einem ApplyUpdates bzw. CommitUpdates wieder weg.
Das heißt im Umkehrschluss, dass ohne CachedUpdates nur der aktuelle Datensatz geändert sein kann?

Und: warum ist bei mir (bei nur einem Record!) dann UpdatesPending auf True gesetzt?

Der Status des aktuellen Records wird in Modified geführt. Es kann aber sein, dass noch nicht alle Änderungen in den datensensitiven Controls berücksichtig wurden. In dem Fall genügt ein Aufruf von UpdateRecord um das zu aktualisieren. Das ist übrigens bei allen DataSets so und hat nichts mit der BDE zu tun.
Also sicherheitshalber immer vor der Status/Modified-Abfrage ein UpdateRecord()-Aufruf einfügen? Oder kann ich irgendwie abfragen, ob das notwendig ist?

Das kann ja dann nur für den aktuellen Record gelten, oder?
Wie ist das bei Master/Detail, wenn die Detail-Datensätze in eine TDBGrid enthalten sind?
Könnte es da mehrere Datensätze geben, bei denen noch ein UpdateRecord gemacht werden muss?

Geändert von Bodenseematze (26. Aug 2024 um 16:13 Uhr) Grund: zu spät - kommt in eigene Antwort...
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#6

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 16:08
Das heißt im Umkehrschluss, dass ohne CachedUpdates nur der aktuelle Datensatz geändert sein kann?
Das weiß ich tatsächlich nicht, da ich die BDE-Sourcen gerade nicht verfügbar habe (ich glaube sogar, die waren nie verfügbar). Ich vermute, dass das aber nicht für den aktuellen Datensatz gilt, da dieser ja bei Cancel nicht in den Update-Buffer übernommen wird.

Und: warum ist bei mir (bei nur einem Record!) dann UpdatesPending auf True gesetzt?
Das kann ich dir aus demselben Grund auch nicht sagen.

Also sicherheitshalber immer vor der Status/Modified-Abfrage ein UpdateRecord()-Aufruf einfügen?
Ja, wenn der State in [dsEdit, dsInsert] ist.

Oder kann ich irgendwie abfragen, ob das notwendig ist?
Nein.

Das kann ja dann nur für den aktuellen Record gelten, oder?
Wie ist das bei Master/Detail, wenn die Detail-Datensätze in eine TDBGrid enthalten sind?
Könnte es da mehrere Datensätze geben, bei denen noch ein UpdateRecord gemacht werden muss?
Jedes DataSet hat seinen eigenen Modified Status, egal ob Master/Detail oder nicht. Es betrifft immer den jeweils aktuellen Datensatz. Wenn du also ein Master- und ein Detail-DataSet hast, dann musst du das bei beiden machen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#7

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 16:25
Das heißt im Umkehrschluss, dass ohne CachedUpdates nur der aktuelle Datensatz geändert sein kann?
Das weiß ich tatsächlich nicht, da ich die BDE-Sourcen gerade nicht verfügbar habe (ich glaube sogar, die waren nie verfügbar). Ich vermute, dass das aber nicht für den aktuellen Datensatz gilt, da dieser ja bei Cancel nicht in den Update-Buffer übernommen wird.
Also bei "normalen" TDataSets (ohne CachedUpdates) bzw. wenn CachedUpdates auf False steht, muss ich über alle Records loopen und deren Modified abgfragen, damit ich herausfinde ob einer der Records geändert ist?
Oder wird dort dann automatisch beim Wechsel des Records die geänderten Daten in die Datenquelle geschrieben?
Dann wäre es in dem Fall ja tatsächlich nur möglich, dass der aktuelle Record Änderungen hat...

Und: warum ist bei mir (bei nur einem Record!) dann UpdatesPending auf True gesetzt?
Das kann ich dir aus demselben Grund auch nicht sagen.
Das finde ich immer noch sehr seltsam und unlogisch!

[EDIT]: ich habe in meinen Quellen mal nachgeschaut, das Property UpdatesPending ist über einen Getter in TBDEDataSet folgendermaßen implementiert:
Delphi-Quellcode:
function TBDEDataSet.GetUpdatesPending: Boolean;
begin
  Result := GetIntProp(FHandle, curDELAYUPDNUMUPDATES) > 0;
end;
Damit bin ich so schlau wie vorher - zumal ich curDELAYUPDNUMUPDATES nirgends definiert finden kann

Und der Aufruf von UpdateStatus() macht auch nur Sinn, wenn CachedUpdates gesetzt ist - nur dann bringt es einen Wert ungleich usUnmodified zurück. Und es bezieht sich wohl auch nur auf den aktuellen Record (zumindest lt. Doku)...

Also sicherheitshalber immer vor der Status/Modified-Abfrage ein UpdateRecord()-Aufruf einfügen?
Ja, wenn der State in [dsEdit, dsInsert] ist.
Das habe ich auch gerade gemerkt - einfach "immer" aufgerufen, fliegt ggf. eine Exception, dass sich "die Datenmenger weder im Editier- noch im Einfügemodus befindet"...
--> dann macht das ja nur Sinn, wenn ich bereits weiß, dass ich im Editier-/Insert-Modus bin und ich Fields auf Änderungen prüfen möchte, oder?
[EDIT]: lt. Embarcadero-Doku ist der Aufruf für die Gegenrichtung zuständig, d.h. es werden die Controls davon informiert, dass sich im Record Änderungen befinden - wenn das so ist, benötige ich es sicherlich für diesen Anwendungsfall hier nicht...

Jedes DataSet hat seinen eigenen Modified Status, egal ob Master/Detail oder nicht. Es betrifft immer den jeweils aktuellen Datensatz. Wenn du also ein Master- und ein Detail-DataSet hast, dann musst du das bei beiden machen.
Ja, das ist schon klar - ich meinte, wenn z.B. im Detail-Grid mehrere Zeilen geändert sind - dann muss ich eine Schleife über alle Records des Detail-DataSet machen und kann nur so herausfinden, ob Records: neu sind oder geändert sind oder gelöscht wurden, oder verstehe ich das immer noch falsch?

Geändert von Bodenseematze (26. Aug 2024 um 17:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#8

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 26. Aug 2024, 18:54
muss ich über alle Records loopen und deren Modified abgfragen, damit ich herausfinde ob einer der Records geändert ist?
Nein, denn lediglich der aktuelle Record kann Modified sein. Alle anderen sind ja nach einer etwaigen Änderung entweder durch Cancel in den ursprünglichen Zustand zurück versetzt oder durch Post gespeichert worden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#9

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 27. Aug 2024, 08:52
muss ich über alle Records loopen und deren Modified abgfragen, damit ich herausfinde ob einer der Records geändert ist?
Nein, denn lediglich der aktuelle Record kann Modified sein. Alle anderen sind ja nach einer etwaigen Änderung entweder durch Cancel in den ursprünglichen Zustand zurück versetzt oder durch Post gespeichert worden.
Das widerspricht jetzt völlig meinem Verständnis.

Wohin wird das denn durch "Post" gespeichert?
Bei der ersten Änderung des Master- oder eines der Detail-Datensätze starte ich auf der Datenbank eine Transaktion - dann können soviel Änderungen durchgeführt werden wie gewünscht.
Und erst wenn alle Änderungen entweder gespeichert (Commit) oder verworfen (Rollback) werden, sind die Änderungen weg.
Und bis dahin muss ich doch programmtechnisch feststellen können, ob sich im Master-Datensatz oder einem der Detail-Datensätze Änderungen (d.h. es sind Daten im Query ggü. dem Datenbankinhalt verändert) befinden.

Und da möchte ich eben verstehen, mit welchen Properties / Aufrufen etc. auf den TQuery / TDataSet (oder auch sonst irgendwie) ich das einfachst möglich - aber korrekt - feststellen kann...
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.354 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: TQuery (BDE) / TDataSet - Verständnisproblem "Modified"

  Alt 27. Aug 2024, 10:24
CachedUpdates sorgt dafür, dass Änderungen nicht sofort an die Datenbank geschickt werden. Deswegen kann man über UpdatesPending prüfen, ob noch was im Cache ist. D.h. man hat zwar lokal (in der Anwendung) Änderungen, aber die stehen noch nicht in der DB. Dafür sorgt dann ApplyUpdates. Bei einem Programmabsturz sind deine lokalen Änderungen dann nicht in der DB. Der Vorteil von CachedUpdates ist der geringere Netzwerkverkehr. Liegt die DB lokal auf dem Anwendungsrechner, bringt CachedUpdates nicht mehr viel.
Schaltet man CacheUpdates aus, müsste UpdatesPending immer False liefern.

Zum Problem:
Du verwendest Queries, wenn ich es richtig gesehen habe. Diese können eigene DML-Anweisungen (Edit, Delete, Insert) haben, die unter Umständen automatisch ausgelöst werden. Selbst wenn keine echten Änderungen vorliegen kann es solche Situationen geben, die manchmal kaum nachvollziehbar sind. Damit meine ich Änderungen, die zwar von der Komponente registriert werden, aber die Inhalte trotzdem unverändert sind. Ein Update ohne inhaltliche Änderungen ist immer noch ein Update. Unter Umständen kann es dann sogar passieren, dass ein ApplyUpdates zu einem Fehler führt.

Die Ursachen können vielfältig und teilweise kaum zu erklären sein. Ich denke aber, dass es nichts mit der BDE zu tun haben wird. Irgendein Event kann bei einem Vergleich zu einem ungewollten Update führen. Eine Formatierung für ein Edit-Feld führt scheinbar zu einer Änderung. Komplexe Master-Detail-Abhängigkeiten können bei manueller Steuerung auch dazu führen. Eine ungewolltes oder unkontrolliertes Edit/Post kann ein LiveUpdate auslösen und dadurch ein UpdatesPending auf True setzen. Ich meine auch mal gelesen zu haben, dass bestimmte Prefixe bei Feldnamen zu so einem Problem geführt haben sollen.

Da du sowieso mit Transaktionen arbeitest, würde ich CachedUpdates deaktivieren. Wenn du nicht gerade Massenänderungen machst, ist der Netzwerkverkehr zu vernachlässigen und in dem Fall könntest du CachedUpdates auch gezielt aktivieren.
Peter
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:05 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