Announcement

Collapse
No announcement yet.

ADO (MS-SQL) + clUseServer + DBGrid-Anbindung

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

  • ADO (MS-SQL) + clUseServer + DBGrid-Anbindung

    Ich habe meine Anwendung für den Zugriff auf MS-SQL-Datenbanken auf ADO (Express) umgestellt.

    Jedoch ist mir folgendes Performance-Grab aufgefallen:
    Öffne ich nun mit obigen Einstellungen (clUseServer + ctKeySet) eine große Tabelle mittels SELECT * FROM <MeineTabelle>, so dauert es relativ lange (mehrere Sekunden). Die gleiche Abfrage über einen BDE + ODBC-Eintrag ergibt keine Verzögerung beim Öffnen der Query-Komponente.

    Alle anderen Einstellungen von CuserType (außer ctKeySet) sind nicht für eine Bindung an ein DB-Grid geeignet (Fehlermeldung, das Datenmenge keine Positionsmarken unterstützt).

    Irgendeine Idee welche Einstellungen performancemäßig gut sind und an ein DB-Grid gebunden werden können.

  • #2
    Hallo,

    &gt;Die gleiche Abfrage über einen BDE + ODBC-Eintrag ....

    weil die BDE "schummelt", indem das Fetchen der Ergebnismenge sofort dann abgebrochen wird, wenn die im TDBGrid sichtbaren Datensätze beim Client eingetroffen sind.

    Generell ist die Einstellung <b>clUseServer</b> nur bei ACCESS-Datenbanken sinnnvoll, um die Doppelpufferung durch die <i>OLE DB Client Cursor Engine</i> zu vermeiden. Bei der Einstellung <b>clUseClient</b> steht das asynchrone Laden der Ergebnismenge im Hintergrund zur Verfügung, so dass im TDBGrid die ersten (sichtbaren) Datensätze wieder sofort angezeigt werden:

    <pre>
    <font color="#003399"><i>{ ************************************************** **************
    Typ : Hauptformular
    Autor : Andreas Kosch
    Compiler : Delphi 5 Enterprise
    Betriebssystem : Windows 2000
    Begonnen am : 22.12.2000
    Beschreibung : Beispiel für das asynchrone Öffnen einer
    Datenmenge, wobei der Ladevorgang abgebrochen
    werden kann. Allerdings ist dies nur dann
    erfolgreich, wenn in OnFetchProgress direkt
    DataSet.RecordSet.Cancel aufgerufen wird,
    der Aufruf von DataSet.Cancel ist wirkungslos
    ************************************************** ************** }</i></font>
    <br>
    <b>unit</b> AsyncCancelFrm;
    <br>
    <b>interface</b>
    <br>
    <b>uses</b>
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls, Db, Grids, DBGrids, ADODB, ComCtrls, ActnList, Menus;
    <br>
    <b>type</b>
    TForm1 = <b>class</b>(TForm)
    ADOConnection1: TADOConnection;
    ADODataSet1: TADODataSet;
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    ButtonOpen: TButton;
    ButtonClose: TButton;
    Label1: TLabel;
    EditLocate: TEdit;
    StatusBar1: TStatusBar;
    ActionList1: TActionList;
    MainMenu1: TMainMenu;
    MFile: TMenuItem;
    MFClose: TMenuItem;
    ActionExit: TAction;
    ActionOpen: TAction;
    ActionClose: TAction;
    MDatabase: TMenuItem;
    MDOpen: TMenuItem;
    MDClose: TMenuItem;
    CheckBoxAsync: TCheckBox;
    ButtonCancel: TButton;
    <b>procedure</b> EditLocateChange(Sender: TObject);
    <b>procedure</b> ActionList1Update(Action: TBasicAction;
    <b>var</b> Handled: Boolean);
    <b>procedure</b> ActionExitExecute(Sender: TObject);
    <b>procedure</b> ActionOpenExecute(Sender: TObject);
    <b>procedure</b> ActionCloseExecute(Sender: TObject);
    <b>procedure</b> ButtonCancelClick(Sender: TObject);
    <b>procedure</b> ADODataSet1FetchProgress(DataSet: TCustomADODataSet;
    Progress, MaxProgress: Integer; <b>var</b> EventStatus: TEventStatus);
    <b>private</b>
    <font color="#003399"><i>{ Private-Deklarationen }</i></font>
    FCancelAsyncLoad : Boolean;
    <b>public</b>
    <font color="#003399"><i>{ Public-Deklarationen }</i></font>
    <b>end</b>;
    <br>
    <b>var</b>
    Form1: TForm1;
    <br>
    <b>implementation</b>
    <br>
    <font color="#003399"><i>{$R *.DFM}</i></font>
    <br>
    <b>procedure</b> TForm1.ActionList1Update(Action: TBasicAction;
    <b>var</b> Handled: Boolean);
    <b>begin</b>
    ButtonOpen.Enabled := <b>not</b> ADODataSet1.Active;
    ButtonClose.Enabled := ADODataSet1.Active;
    Handled := True;
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.EditLocateChange(Sender: TObject);
    <b>var</b>
    sTxt : <b>String</b>;
    <b>begin</b>
    sTxt := EditLocate.Text;
    <b>if</b> sTxt &lt;&gt; <font color="#9933CC">''</font> <b>then</b>
    <b>with</b> ADODataSet1 <b>do</b>
    Locate(<font color="#9933CC">'PLZ'</font>, sTxt, [loCaseInsensitive, loPartialKey]);
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.ActionExitExecute(Sender: TObject);
    <b>begin</b>
    Close
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.ActionOpenExecute(Sender: TObject);
    <b>begin</b>
    FCancelAsyncLoad := False;
    <b>if</b> CheckBoxAsync.Checked <b>then</b>
    ADODataSet1.ExecuteOptions := [eoAsyncFetchNonBlocking]
    <b>else</b>
    ADODataSet1.ExecuteOptions := [];
    ADODataSet1.Active := True;
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.ButtonCancelClick(Sender: TObject);
    <b>begin</b>
    FCancelAsyncLoad := True;
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.ActionCloseExecute(Sender: TObject);
    <b>begin</b>
    ADODataSet1.Active := False;
    <b>end</b>;
    <br>
    <b>procedure</b> TForm1.ADODataSet1FetchProgress(DataSet: TCustomADODataSet;
    Progress, MaxProgress: Integer; <b>var</b> EventStatus: TEventStatus);
    <b>begin</b>
    StatusBar1.SimpleText := Format(<font color="#9933CC">'%d Datensätze geladen'</font>,
    [DataSet.RecordCount]);
    <b>if</b> FCancelAsyncLoad <b>then</b>
    DataSet.RecordSet.Cancel; <font color="#003399"><i>// DataSet.Cancel ist wirkungslos !</i></font>
    Application.ProcessMessages;
    <b>end</b>;
    <br>
    <b>end</b>.
    </pre&gt

    Comment


    • #3
      Hallo Andreas,

      diese Option hab ich Glad übersehen. :-)
      Wenn ich die Option setze, wird das Performanceproblem um einiges entschärft

      Comment


      • #4
        Hallo,
        die Lösung ist ja im Ansatz ganz nett, aber kann ich auch die komplette Funktionalität eines DBGrids bekommen? Also daß er beim runterscrollen die nächsten Datensätze nachlädt?

        Der BeforeScroll-Event des ADODataSets würde sich anbieten, da er genau zum richtigen Zeitpunkt erfolgt. Leider weiß ich nicht, wie ich dem RecordSet sagen soll, die unterbrochene DB-Verbindung wieder aufzunehmen

        Comment

        Working...
        X