Announcement

Collapse
No announcement yet.

TADODataSet / FieldDefs.Add / CreateField

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TADODataSet / FieldDefs.Add / CreateField

    Hallo,
    <br>
    <br>Habe ein ADODataSet1 bei dem zwei Felder mittels Feld Editor hinzugefügt werden.
    <pre>
    procedure TForm1.MyValidate(Sender: TField);
    begin
    Edit1.Text := 'XXXXXXXXXXXX';//Sender.asString;
    If Sender.asString = 'X' Then begin
    Edit1.Text := 'YYYYYYYYYYY';//Sender.asString;
    Sender.asString := 'XXXX';
    end
    else
    //Edit1.Text := 'ZZZZZZZZZZZ';//Sender.asString;
    Edit1.Text := Sender.asString;//Sender.asString;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    Var
    I : Integer;
    begin
    ADODataSet1.Fields.FindField('Name').OnValidate := MyValidate;
    ADODataSet1.Open;
    end;
    </pre>
    <br>Gibt man nun in dem Feld Name ein "X" ein , so wird daraus ein "XXXXXX".
    <br>Werden jedoch die Felder des Datasets mittels FeldEditor gelöscht und der folgende Code in "TForm1.FormCreate" eingefügt, dann ...
    <pre>
    procedure TForm1.FormCreate(Sender: TObject);
    Var
    I : Integer;
    begin
    with ADODataSet1 do
    begin
    FieldDefs.Clear;
    FieldDefs.Add('id', ftInteger,0,False);
    FieldDefs.Add('Name', ftString,50,False);
    for I := 0 to FieldDefs.Count - 1 do begin
    with FieldDefs[I] do begin
    CreateField(nil);
    end;
    end;
    end;
    ADODataSet1.Fields.FindField('Name').OnValidate := MyValidate;
    ADODataSet1.Open;
    end;
    </pre>
    <br>... dann wird aus der Eingabe "X" ein "X". Es scheint sogar so, das aus der Eingabe "X" ein "XXXXXX" und direkt danach wieder ein "X" wird.
    <br>
    <br>1) Aber was fehlt denn noch zur richtigen Definition der Felder? Das selbe Phänomen bekomme ich auch bei TClientDataset, MemoryData- Komponenten.
    <br>
    <br>2) Eine Temporäre Tabelle (im Ram) kann man doch auch mit einem ADO Recordset erstellen, oder? Wenn ja wie kann man denn einer DataSource sagen, das diese auf ein Recordset zugreifen soll. Kann man einem Recordset zur Laufzeit auch OnValidate Ereignisse zuordnen?
    <br>
    <br>3) Wieso gibt es eigentlich MemData Komponenten, wenn man doch genau das gleiche auch mit einem ADO Recordset oder einem TClientDataSet machen kann?
    <br>
    <br>4) Was sollte man verwenden, wenn man eine Temporäre Tabelle zur Laufzeit (im Ram) erstellen will, und bestimmten Feldern OnValidate Ereignisse zuordnen will?
    <br>
    <br>Danke!
    <br>
    <br>mfg
    <br>PS

  • #2
    Hallo,

    zur Frage 1: <br>
    Das Problem liegt in der falschen Herangehensweise - daher tritt das Problem auch mit allen Komponenten auf. Der Sinn von <b>OnValidate</b> liegt darin, ein Veto (Exception) einzulegen - so wie das auch in der Delphi-Hilfe beschrieben wird. Wenn der Wert des Feldes geändert werden soll, kann man zu <b>OnChange</b> greifen.

    zur Frage 2: <br>
    Ja, alle Aufgaben sind möglich (siehe Beispielprojekt).

    zur Frage 3: <br>
    Das hat 2 Gründe:<br>
    1. Es gibt viele, denen die ADO-Fähigkeiten unbekannt sind <br>
    2. Es gibt Entwickler, die müssen einfach alles selbst schreiben, weil sie der Auffassung sind, das alle anderen nur unbrauchbaren Schrott produzieren :-)

    zur Frage 4: <br>
    Siehe Beispiel:

    Beispielprojekt demonstriert eine RAM-Tabelle über ein ADO-RecordSet, dass über eine später angeflanschte TADODataSet-Komponenten und TDataSource in einem TDBGrid angezeigt und bearbeitet werden kann. Der umständliche Weg über das RecordSet-Objekt macht nur dann Sinn, wenn die Tabellenstruktur erst zur Laufzeit, aber nicht bereits über den Objektinspektor zur Entwicklungszeit festgelegt werden soll. Nach dem Anhängen der "lebenden" RecordSet-Objektinstanz an TADODataSet hat TADODataSet keine Ahnung davon, dass es sich um eine In-Memory-Table handelt :-)

    Das Beispiel wurde mit Delphi 6 geschrieben, nach dem Entfernen der Unit Variants läuft es aber auch mit Delphi 5:
    <pre>
    unit ADO_ValidateProblemFrm;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls, Grids, DBGrids, DB, ADODB, ExtCtrls, DBCtrls;

    type
    TForm1 = class(TForm)
    ADODataSet1: TADODataSet;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    ButtonMakeTable: TButton;
    Memo1: TMemo;
    DBNavigator1: TDBNavigator;
    procedure ButtonMakeTableClick(Sender: TObject);
    private
    { Private-Deklarationen }
    procedure MyValidate(Sender: TField);
    procedure MyChange(Sender: TField);
    public
    { Public-Deklarationen }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    uses ComObj, ADOInt;

    procedure TForm1.ButtonMakeTableClick(Sender: TObject);
    var
    aRS : _RecordSet;
    begin
    aRS := CreateComObject(CLASS_Recordset) as _Recordset;
    with aRS do
    begin
    CursorLocation := adUseClient;
    // Recordset mit eigener Datenstruktur erstellen
    Fields.Append('Name', adVarChar, 15, adFldUnspecified);
    Fields.Append('Vorname', adVarChar, 15, adFldUnspecified);
    Fields.Append('eMail', adVarChar, 15, adFldUnspecified);
    // Recordset öffnen
    Open(EmptyParam, EmptyParam, adOpenUnspecified,
    adLockUnspecified, 0);
    end;
    with ADODataSet1 do
    begin
    // RecordSet-Objekt an TADODataSet anhängen
    Recordset := aRS;
    // Testdatensatz einfügen
    AppendRecord(['Test','Test','Test']);
    Fields.FindField('Name').OnValidate := MyValidate;
    Fields.FindField('Name').OnChange := MyChange;

    end;
    end;

    procedure TForm1.MyChange(Sender: TField);
    begin
    with ADODataSet1 do
    begin
    if FieldByName('Name').Value = 'Y' then
    FieldByName('Name').Value := 'Z';
    end;
    end;

    procedure TForm1.MyValidate(Sender: TField);
    begin
    Memo1.Lines.Add('MyValidate: ' + Sender.AsString);
    if Sender.AsString = 'X' then
    Abort;
    end;

    end.
    </pre&gt

    Comment


    • #3
      Vielen Dank!
      <br>
      <br>mfg
      <br>P

      Comment

      Working...
      X