Announcement

Collapse
No announcement yet.

ADO Connection ???

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

  • ADO Connection ???

    Hallo,

    ich habe hier vor kurzem geschrieben das ich bei Benutzung von Client Datasets nicht immer den Primärschlüssel zurückbekomme. Nach diversen Tests habe ich folgendes festgestellt:

    Der Schlüssel wird immer übergeben wenn das DataSet mit einem eigenen Connection String auf den MS SQL Server zugreift.

    Der Schlüssel wird bei einem Connection Object nur bei den ersten 2-3 DataSets übergeben die mit ihm verbunden sind. DataSets die erst später im Programm Aktiviert werden, bekommen keine Primärschlüssel mehr zurück.

    Die Entscheidung ob ich hunderte von Connections am SQL-Server habe oder
    hunderte von Server Cursorn ist nicht gerade sehr berauschend für eine gute
    Performance

    Die DataSets nach dem Laden vom Server zu trennen und bei Änderungen wieder neu zu verbinden, ist ehrlich gesagt auch nicht sehr ....

    Ich hoffe mir kann jemand erklären was ich beachten muss.

    Danke, Stefan.

  • #2
    Hallo,

    das Konzept von ADO unterscheidet sich grundlegend (nicht allein infolge der bewegten Vergangenheit ODBC, DAO, RDO) von der gewohnten BDE. Historisch ist ADO als Datenbank-Schnittstelle für Active Server Pages entstanden - und in dieser Umgebung haben dauerhafte Connections noch nie eine Rolle gespielt.

    In einer Three-tier-Anwendung werden die ADO-Objekte in der mittleren Schicht ausgeführt, wobei der MTS/COM+ dafür sorgt, der der automatische Datenbankverbindungs-Pool des Resource Dispensers zur Verfügung steht. Wenn ein Client eine Interface-Methode seines Applikation-Objekts aufruft, wird nur für die Zeitdauer dieses Aufrufs eine Connection hergestellt und am Ende der Methode sofort wieder freigeben. Da der Resource Dispenser den Connect/Disconnect abfängt und die aktive Verbindung zurück in den Pool legt, verursacht das keine spürbare Zeitverzögerung.

    Das könnte zum Beispiel in COM+ so aussehen - die Connection zum SQL Server 7 wird angefordert, die Stored Procedure wird aufgerufen und die Connection wird geschlossen:
    <pre>
    procedure TOSTTDBObj.DoTransfer(cValue: Currency;
    iKdnNr: Integer; out sMsg: WideString);
    var
    iError : Integer;
    sError : String;
    begin
    sError := '-';
    ADOConnection1.Connected := True;
    SetAbort;
    try
    with ADOStoredProcTransfer do
    begin
    Parameters[1].Value := cValue;
    Parameters[2].Value := iKdnNr;
    ExecProc;
    end;
    for iError := 0 to ADOConnection1.Errors.Count - 1 do
    sError := sError +
    ADOConnection1.Errors[iError].Description + #10#13;
    sMsg := sError;
    finally
    ADOConnection1.Connected := False;
    end;
    if sMsg = '-' then
    SetComplete;
    sMsg := sMsg +
    Format(' %d: %m DM gebucht + SetComplete aufgerufen.',
    [iKdnNr, cValue]);
    end;
    </pre>
    Und in dieser Umgebung spielen die Nachteile von ADO keine Rolle mehr. Ausserdem ist es generell keine gute Idee, auf Server Cursor zurückzugreifen. Microsoft hat dazu im <i>SQL Server 7 Developers Resource Kit</i> eine TechDoc veröffentlicht (ist auch im Buch <i>Inside Microsoft SQL Server 7</i> zu finden), die den Flurschaden im Detail beschreibt, den ein Server Cursor anrichtet

    Comment


    • #3
      Hallo,

      bei StoredProcs hab ich damit ja kein Problem wie ist es aber wenn
      ich mit den Ergebnismengen am Client arbeiten will. Muss ich dann
      das DataSet von der Connection trennen und später wieder damit verbinden ?

      Vielleicht kannst du mir hier noch einen Tipp geben.

      Danke

      Comment


      • #4
        Hallo,

        die Antwort auf diese Frage hängt davon ab, wieviel Anwender gleichzeitig mit dem Programm arbeiten. Steht die Performance im Mittelpunkt, würde ich alle SELECT/INSERT/UPDATE-Anweisungen nur über Stored Procedures laufen lassen und auf die RecordSets von ADO ganz verzichten. In diesem Fall tauchen beim Client <b>keine</b> Datensteuerungs-Komponenten auf, sondern nur ganz normale Controls (TEdit, TCombobox, TMemo etc.).

        In einem moderaten Benutzer-Umfeld ist gegen Recordset-Objekte nichts einzuwenden. Vor der Rückgabe an den Client wird die Connection des noch aktiven Recordset-Objekts getrennt:
        <pre>
        function TADOServer.ReturnRS: OleVariant;
        var
        adoCon1: _Connection;
        adoRs1: _Recordset;
        begin
        adoCon1 := CoConnection.Create;
        adoRs1 := CoRecordset.Create;
        adoCon1.CursorLocation := adUseClient;
        adoCon1.Open(cConnStr, '', '', 0);
        adoRs1.Open('SELECT * FROM Country', adoCon1, adOpenKeyset,
        adLockBatchOptimistic, 0);
        // vollständiges ADO-Recordset zurückliefern
        Result := adoRs1;
        adoRs1.Set_ActiveConnection(nil);
        adoCon1.Close;
        end;
        </pre>
        Der COM-Client kommt vollständig ohne eigene ADO-Verbindung aus, statt dessen übernimmt die TADOTable-Instanz im Formular die Daten vom RecordSet-Objekt des COM-Servers:
        <pre>
        procedure TForm1.ButtonGetClick(Sender: TObject);
        var
        aSrv : IADOServer;
        aRS : _Recordset;
        begin
        aSrv := CoADOServer.Create;
        aRS := IDispatch(aSrv.ReturnRS) as _Recordset;
        ADOTable1.Recordset := aRS;
        ADOTable1.Active := True;
        end;
        </pre>
        Auf dem gleichen Weg kann der Client alle seine Änderungen wieder vom Application-Objekt in der Datenbank einarbeiten lassen. Das Application-Objekt übernimmt dabei vom Client das Recordset-Objekt und ruft die Methode UpdateBatch auf:
        <pre>
        function TRDSAppServer.Update(const RS: _Recordset): Integer;
        var
        aRS : _RecordSet;
        ConnStr : WideString;
        begin
        ConnStr := 'FILE NAME=' + DataLinkDir + '\DBDEMOS.UDL';
        aRS := CoRecordset.Create;
        aRS.Open(RS, ConnStr, TOleEnum(adOpenUnspecified),
        TOleEnum(adLockUnspecified),
        TOleEnum(adCmdUnspecified));
        aRS.UpdateBatch(adAffectAll);
        Result := 1;
        end;
        </pre>
        Der Client übergibt sein Recordset-Objekt beim Aufruf der Interface-Methode des Servers als Parameter:
        <pre>
        procedure TForm1.ButtonUpdateClick(Sender: TObject);
        begin
        RDSConnection1.AppServer.Update(Employee.Recordset );
        end;
        </pre>

        P.S: Die Beispiele habe ich aus Faulheit aus verschiedenen Beispielprojekten kopiert, die ich auf den <i>Entwickler-Tagen 2000</i> vorgestellt habe

        Comment

        Working...
        X