Einzelnen Beitrag anzeigen

Benutzerbild von Coder90
Coder90

Registriert seit: 8. Nov 2004
Ort: Ebhausen, BW
44 Beiträge
 
Delphi 2007 Architect
 
#1

Bookmarks werden bei Änderungen ungültig

  Alt 15. Dez 2007, 18:17
Datenbank: XML • Zugriff über: TXMLTransform
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.
Angehängte Dateien
Dateityp: zip vstxmldb_972.zip (10,7 KB, 7x aufgerufen)
  Mit Zitat antworten Zitat