Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Bookmarks werden bei Änderungen ungültig (https://www.delphipraxis.net/105097-bookmarks-werden-bei-aenderungen-ungueltig.html)

Coder90 15. Dez 2007 18:17

Datenbank: XML • Zugriff über: TXMLTransform

Bookmarks werden bei Änderungen ungültig
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi
Ich arbeite mit XML-Dateien welche ich über TXMLTransform und TClientDataSet in einem VirtualTreeView darstelle.
Die Darstellung funktioniert ohne Probleme.
Aber sobald ich Daten in der XML-Datenbank ändere kommt es zu Zugriffsverletzungen da TBookmarks ungültig werden.

Ich hab ein Testprojekt erstellt um den Fehler leichter zu finden.
Hier der Quelltext:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, VirtualTrees, DB, DBClient, xmldom, Provider, Xmlxform,
  Grids, DBGrids;

type

  PNodeData = ^TNodeData;
  TNodeData = record
    FBookmark: TBookmark;
  end;

  TForm1 = class(TForm)
    VST: TVirtualStringTree;
    btnLoad: TButton;
    ClientDataSet: TClientDataSet;
    XMLTransformProvider: TXMLTransformProvider;
    DataSource: TDataSource;
    DBGrid1: TDBGrid;
    btnAdd: TButton;
    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
    procedure btnLoadClick(Sender: TObject);
    procedure VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; NewText: WideString);
    procedure btnAddClick(Sender: TObject);
    procedure VSTGetNodeDataSize(Sender: TBaseVirtualTree;
      var NodeDataSize: Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnAddClick(Sender: TObject);
var
  Node: PVirtualNode;
  NodeData: PNodeData;
begin
  ClientDataSet.Append;
  ClientDataSet.FieldValues['test'] := '123';
  ClientDataSet.Post;

  Node := VST.AddChild(nil);
  NodeData := VST.GetNodeData(Node);
  NodeData^.FBookmark := ClientDataSet.GetBookmark;
end;

procedure TForm1.btnLoadClick(Sender: TObject);
var
  Node: PVirtualNode;
  NodeData: PNodeData;
begin
  XMLTransformProvider.XMLDataFile := 'test.xml';
  ClientDataSet.XMLData := XMLTransformProvider.TransformRead.Data;
  ClientDataSet.DisableControls;
  try
    ClientDataSet.First; //Auf ersten Datensatz positionieren, EOF wird dadurch auf False gesetzt
    while not ClientDataSet.Eof do // Schleife durchlaufen, bis EOF True ist.
    begin
      Node := VST.AddChild(nil);
      NodeData := VST.GetNodeData(Node);
      NodeData^.FBookmark := ClientDataSet.GetBookmark;
      ClientDataSet.Next; //EOF ist True, wenn Next scheitert, da dann der letzte Datensatz erreicht wurde
    end;
  finally
    ClientDataSet.EnableControls;
  end;
end;

procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  NodeDataSize := SizeOf(PNodeData);
end;

procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
begin
  ClientDataSet.GotoBookmark(TBookmark(PNodeData(Sender.GetNodeData(Node)).FBookmark));
  CellText := ClientDataSet.FieldByName('test').asString;
end;

procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; NewText: WideString);
var
  NodeData: PNodeData;
begin
  ClientDataSet.GotoBookmark(TBookmark(PNodeData(Sender.GetNodeData(Node)).FBookmark));
  ClientDataSet.Edit;
  ClientDataSet.FieldValues['test'] := NewText;
  ClientDataSet.Post;
  //NodeData := VST.GetNodeData(Node);
  //NodeData^.FBookmark := ClientDataSet.GetBookmark;
  ClientDataSet.GotoBookmark(TBookmark(PNodeData(Sender.GetNodeData(Node)).FBookmark));
end;

end.
Die XML-Datei wird mit klick auf "Load" geladen.
Mit "Add" werden Datensätze hinzugefügt.
Klickt man nun zweimal auf einen Knoten und ändert dessen Beschriftung kommt es zur Zugriffsverletzung:
Zitat:

Im Projekt Project1.exe ist eine Exception der Klasse EDatabaseError mit der Meldung 'ClientDataSet: Datensatz nicht gefunden' aufgetreten.
Dies passiert jedoch nur bei neu hinzugefügten Knoten und auch nicht dem zuletzt hinzugefügtem Knoten.

Entkommentiert man Zeile 104 und 105 passiert dieser Fehler nicht mehr und alles funktioniert.
Dort wird nach dem Bearbeiten das TBookmark des Datensatzes erneut dem Knoten zugewiesen.

Nun bin ich mir nicht sicher ob das eine saubere Lösung ist, nach jedem Bearbeiten den TBookmark neu zuzuweißen.
Vielleicht ist der Fehler ja auch woanders?

Hab das Projekt angehängt.

Die Muhkuh 15. Dez 2007 18:18

Re: Bookmarks werden bei Änderungen ungültig
 
Zitat:

Zitat von Coder90
Hab das Projekt angehängt.

Hast Du nicht :tongue:

Coder90 15. Dez 2007 18:21

Re: Bookmarks werden bei Änderungen ungültig
 
Zitat:

Zitat von Die Muhkuh
Zitat:

Zitat von Coder90
Hab das Projekt angehängt.

Hast Du nicht :tongue:

Doch ;P *bäh*

alzaimar 16. Dez 2007 07:51

Re: Bookmarks werden bei Änderungen ungültig
 
Soweit ich weiss, *werden* Bookmarks ungültig, wenn man Daten des 'gebookmarkten' Records ändert.
Abhilfe: Merke Dir die Datensatznummer oder den Primary Key.

Coder90 16. Dez 2007 13:20

Re: Bookmarks werden bei Änderungen ungültig
 
ich machs jetzt mit findkey.
das klappt besser.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:17 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