Announcement

Collapse
No announcement yet.

ADO - Tabelle im Speicher

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

  • ADO - Tabelle im Speicher

    Also ich konvertiere alte DBASE-Daten das heist diese Tabellen werden nicht verändert. Es sind aber sehr viele Lesezugriffe notwendig bis alle Daten zusammengeführt sind. Ich denke mir nun halt wenn ich diese Tabellen aus den gelesen wird über die schon mehrmals erwähnte aber nicht wirklich beschriebene Methode das die ganze Tabelle im Speicher des Clients abgelegt wird, die Konvertierzeit trastisch verringern darf. Nun Herr Kosch verweist immer auf Sein Buch ADO und Delphi. Ich verstehe ja das er mehr Exemplare davon verkaufen will. Wir haben es auch schon bestellt aber es dauert halt bi es seinen Weg nach Österreich gefunden hat (Mitte April) Diese Zeit haben wir aber nicht mehr.

    Kann mir bitte jemand ein nachvollziehbares Beispiel geben wie ich Tabellen in den Speicher abbilden kann mittels ADO???

    Vielen Dank

    Euer Peter

  • #2
    Hallo,

    >...Wir haben es auch schon bestellt ...

    ja wenn da so ist, kann ich ja auch schon einmal eines der Beispielprojekte aus dem Buch vorab zeigen :-)

    Im Buch stelle ich TClientDataset und das ADO-Recordset in einem Vergleich gegenüber, wobei die Aufgabe darin besteht, 50 000 Datensätze in eine In-Memory-Tabelle einzufügen als Datei zu speichern (damit diese Daten später bei Bedarf neu aus der Datei eingelesen werden können). Der direkte Vergleich zeigt, dass TClientDataset beim Einfügen der Datensätze (In-Memory-Tabelle) mehr als doppelt so langsam ist wie ADO (Recordset-Objekt) :-)

    Die Struktur der In-Memory-Tabelle wird festgelegt, indem die Methode <b>Append</b> der <b>Fields</b>-Kollektion des Recordset-Objekts aufgerufen wird. Anschliessend kann das bereits "lebende" Recordset als Datenquelle der TADODataSet-Instanz untergeschoben werden:

    <pre>
    { ************************************************** **************
    Autor : Andreas Kosch
    Compiler : Delphi 6.0 Enterprise
    Betriebssystem : Windows 2000 SP2
    Erstellt am : 06.08.2001
    Beschreibung : Testprogramm für das Einfügen von
    50000 Datensätzen in eine RecordSet-
    instanz, deren Struktur im eigenen Programm
    definiert wurde.
    ************************************************** ************** }

    unit ADOPerfTestFrm;

    interface

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

    type
    TFormMain = class(TForm)
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    StatusBar1: TStatusBar;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    DBNavigator1: TDBNavigator;
    ToolButton2: TToolButton;
    ProgressBar1: TProgressBar;
    ToolButton3: TToolButton;
    ADODataSet1: TADODataSet;
    procedure FormCreate(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    FormMain: TFormMain;

    implementation

    {$R *.dfm}

    uses ADOInt, ActiveX, ComObj;

    procedure TFormMain.FormCreate(Sender: TObject);
    var
    aRS : _Recordset;
    begin
    aRS := CoRecordset.Create;
    with aRS do
    begin
    CursorLocation := adUseClient;
    Fields.Append('INT', adInteger, 4, adFldUnspecified);
    Fields.Append('VARCHAR', adVarChar, 75, adFldUnspecified);
    Open(EmptyParam, EmptyParam, adOpenUnspecified,
    adLockUnspecified, 0);
    end;
    with ADODataSet1 do
    begin
    RecordSet := aRS;
    Active := True;
    end;
    end;

    procedure TFormMain.ToolButton1Click(Sender: TObject);
    resourcestring
    cFmt = '%d Datensätze in %d Ticks hinzugefügt (Speichern: %d Ticks)';
    cFV1 = 'Ein kurzer Dummy-Eintrag für die VARCHAR-Spalte.';
    cFV2 = 'Ein etwas längerer Dummy-Eintrag für die VARCHAR-Spalte.';
    var
    i, iStart, iStop, iStop2 : Integer;
    begin
    ADODataSet1.DisableControls;
    Statusbar1.SimpleText := 'Daten werden eingefügt...';
    Application.ProcessMessages;
    iStart := GetTickCount;
    try
    with ADODataSet1 do
    for i := 0 to 50000 do
    begin
    Append;
    Fields[0].Value := i;
    if (i mod 5) = 0 then
    Fields[1].Value := cFV1
    else
    Fields[1].Value := cFV2;
    Post;
    if (i mod 500) = 0 then
    begin
    ProgressBar1.StepIt;
    Application.ProcessMessages;
    end;
    end;
    finally
    ProgressBar1.Position := 0;
    ADODataSet1.EnableControls;
    end;
    iStop := GetTickCount;
    ADODataSet1.SaveToFile('ADOPerfTest.dat', pfADTG);
    iStop2 := GetTickCount;
    Statusbar1.SimpleText := Format(cFmt,
    [ADODataSet1.RecordCount, iStop - iStart, iStop2 - iStop]);
    end;

    end.
    </pre&gt

    Comment


    • #3
      Danke,

      Eine Frage hätte ich noch:

      Also wie bereits beschrieben ich habe mehrere DBASe Tabellen die es gitl in jeh eine In-Memory-Tabelle einzulesen damit es einfach schneller geht.

      Habe versucht die den RecordSet der DBASE Tabelle in das ADODataset Objekt zu kopieren.

      .) wenn ich sage ADODATASet1.Recordset := aRS(DBase Tabelle) kommt
      die Fehelrmeldung nicht erlaubt.
      .) wenn ich versuche eine Schleife zu bauen in dem ich Feld für
      Feld in der DataSet anlege scheitere ich daran das ich
      über den aRS der DBAse Tabelle nicht auf die Feldnamen und
      Feldtypen,... zugreifen kann.

      Oder gibts da vielleicht eine einfachere Möglichkeit den DBase REcordSet in die ADODataset1 zu kopieren.

      vielen Dank
      für die Bemühungen

      Pete

      Comment


      • #4
        Hallo,

        &gt;Oder gibts da vielleicht eine einfachere Möglichkeit den DBase RecordSet in die ADODataset1 zu kopieren.

        ein Recordset-Objekt mit der Einstellung CursorLocation = <b>clUseClient</b> verwendet implizit einen Puffer im eigenen Arbeitsspeicher (d.h. die OLE DB Client Cursor Engine lädt alle Datensätze der Tabelle in den Arbeitsspeicher). Man hat also je nach Aufgabenstellung die Wahl zwischen<br>
        a) Recordset-Struktur neu anlegen und Datensätze dort reinkopieren, oder<br>
        b) Recordset direkt für die dBASE-Tabelle öffnen und über den Automatismus von clUseClient puffern lassen<br>

        Der Fall b) könnte zum Beispiel so aussehen: <br>
        1. Connection aufbauen <br>
        2. Recordset mit <b>clUseClient</b> für die dBASE-Tabelle anfordern <br>
        3. Recordset-Datenmenge über <b>Filter</b> eingrenzen <br>
        4. Feldinhalte über <b>Collect</b> auslesen/anzeigen<br>
        Über die <b>Supports</b>-Methode kann das Programm bei ADO nachfragen, welche Operationen für diese Datenmenge zulässig sind:
        <pre>
        uses ADOInt;

        procedure TForm1.Button1Click(Sender: TObject);
        resourcestring
        cCS = 'Provider=Microsoft.Jet.OLEDB.4.0;' +
        'Data Source=C:\Programme\Gemeinsame Dateien\Borland Shared\Data\;' +
        'Extended Properties=dBASE 5.0;Persist Security Info=False';
        var
        aCon : _Connection;
        aRS : _Recordset;
        begin
        aCon := CoConnection.Create;
        aCon.CursorLocation := adUseClient;
        aCon.Open(cCS, '', '', adConnectUnspecified);
        try
        aRS := CoRecordSet.Create;
        aRS.CursorLocation := adUseClient;
        try
        aRS.Open('SELECT * FROM clients.dbf', aCon, adOpenStatic, adLockReadOnly, adCmdText);
        ShowSupports(aCon, aRS);
        // Optional: Datenmenge über FILTER eingrenzen
        aRS.Filter := 'CITY=' + QuotedStr('Los Altos');

        while not aRS.EOF do
        begin
        Memo1.Lines.Add(aRS.Collect[0] + ' ' + aRS.Collect[1]);
        aRS.MoveNext;
        end;
        finally
        aRS.Close;
        end;
        finally
        aCon.Close;
        end;
        end;
        //
        // Supports ermittelt die verfügbaren Funktionen
        //
        procedure TForm1.ShowSupports(aCon : _Connection; aRS : _Recordset);
        begin
        ListBoxLog.Items.Add('Provider = ' + aCon.Provider);
        if aRS.CursorLocation = adUseClient then
        ListBoxLog.Items.Add('CursorLocation = clUseClient')
        else
        ListBoxLog.Items.Add('CursorLocation = clUseServer');
        if aRS.Supports(adBookmark)then
        ListBoxLog.Items.Add('adBookmark = Ja')
        else
        ListBoxLog.Items.Add('adBookmark = Nein');
        if aRS.Supports(adFind)then
        ListBoxLog.Items.Add('adFind = Ja')
        else
        ListBoxLog.Items.Add('adFind = Nein');
        if aRS.Supports(adSeek)then
        ListBoxLog.Items.Add('adSeek = Ja')
        else
        ListBoxLog.Items.Add('adSeek = Nein');
        end;
        </pre&gt

        Comment

        Working...
        X