Announcement

Collapse
No announcement yet.

ADO und Delphi: Alle Verbindungen zum SQL Server zur Laufzeit trennen

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

  • ADO und Delphi: Alle Verbindungen zum SQL Server zur Laufzeit trennen

    Hallo,

    ich entwickle ein Anwendung mit Delphi 6 und SQL-Server7/2000. Ich arbeite mit den ADO-Express-Komponenten, halte aber keine Datenmengen im Speicher. Alle Daten werden mit Hilfe von TADOQuery nur eingelesen und sofort wieder geschlossen. Alle Queries werden über eine einzige TADOConnection mit der Datenbank verbunden (die natürlich intern mehrere Verbindungen öffnet).

    Problem:
    Die Anwendung soll selber für die eigene Datenbank ein Restore ausführen können. Dafür ist es notwendig, dass kein User mehr auf die Datenbank zugreift. Ich schließe deshalb die Connection (und damit alle eventuell noch offenen Queries). Eine zweite Connection verbindet sich mit der master-Datenbank und ermittelt die noch aktiven User auf der Anwendungsdatenbank. Dabei zeigt sich, dass genau 1 Verbindung bestehen bleibt.

    Frage:
    Gibt es eine Möglichkeit, über Transact-SQL serverseitig diese Verbindung zu trennen?
    Oder kann die Anwendung clientseitig diese Verbindung trennen?

  • #2
    Hallo,

    >Dabei zeigt sich, dass genau 1 Verbindung bestehen bleibt.

    das ist der automatisch Datenbankverbindungs-Pool (<i>OLE DB Resource Pooling</i>) von ADO. Wenn das Programm eine Datenbankverbindung trennt, wird nur die aktive (!) Datenbankverbindung zurück in den Pool gelegt.

    Um den automatischen Datenbankverbindung-Pool abzuschalten, muss im Verbindungstring die Zeichenfolge <b>OLE DB Services = -8;</b> (die bedeutet "<i>All except pooling, automatic transaction enlistment, and Client Cursor Engine</i>") verwendet werden. Die Anweisung OLE DB Services=-8 wird jedoch nur dann berücksichtigt, wenn kein Client Cursor verwendet wird.

    Das folgende Beispiel stammt aus meinem Buch <i>ADO und Delphi</i>, sowohl bei TADOConnection als auch bei TADODataSet muss der Wert <b>clUseServer</b> für die Eigenschaft CursorLocation genutzt werden. Je nach dem über die Checkbox auswählbaren ConnectionString verhält sich die Anwendung unterschiedlich. Über den <i>Profiler</i> des MS SQL Server ist das Laufzeitverhalten sehr gut sichtbar,wenn man dort den Verbindungsaufbau/abbau mitprotokollieren lässt:
    <pre>
    unit KillConnectionFrm;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    Db, Grids, DBGrids, ADODB, StdCtrls;

    type
    TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    ADODataSet1: TADODataSet;
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    CheckBoxConnect: TCheckBox;
    ADODataSet1CustomerID: TWideStringField;
    ADODataSet1CompanyName: TWideStringField;
    ADODataSet1ContactName: TWideStringField;
    CheckBoxOLEDBServices: TCheckBox;
    MemoConnectionString: TMemo;
    procedure CheckBoxConnectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    private
    { Private-Deklarationen }
    FOrgConnectionString : WideString;
    FNewConnectionString : WideString;
    public
    { Public-Deklarationen }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.CheckBoxConnectClick(Sender: TObject);
    begin
    if CheckBoxConnect.Checked then
    begin
    if CheckBoxOLEDBServices.Checked then
    ADOConnection1.ConnectionString := FNewConnectionString
    else
    ADOConnection1.ConnectionString := FOrgConnectionString;
    ADOConnection1.Connected := True;
    ADODataSet1.Active := True;
    end
    else
    begin
    ADODataSet1.Active := False;
    ADOConnection1.Connected := False;
    end;
    with MemoConnectionString do
    begin
    Lines.Clear;
    Lines.Add(ADOConnection1.ConnectionString);
    end;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    FOrgConnectionString := 'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=Northwind;Data Source=(local);';
    FNewConnectionString := 'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=Northwind;Data Source=(local);OLE DB Services=-8;';
    end;

    end.
    </pre&gt

    Comment


    • #3
      Hallo,
      auch ich suche zu obigem Problem eine Lösung. Den Vorschlag von Herrn Kosch habe ich erfolglos getestet. Abgesehen davon wäre mir die alleinige Nutzung von "clUseServer" nicht recht. Gibt es weitere Lösungen

      Comment


      • #4
        Hallo,
        habe inzwischen eine Notlösung gefunden:
        Ermitteln wer greift auf die DB zu "sp_who",
        Killen dieser Zugriffe mit "kill Spid" (natürlich mit entsprechenden Abfragen,Warnungen,..).
        Wolfgan

        Comment


        • #5
          Hallo,

          danke schön für den Tipp mit Kill spid. Auch ich brauche den Cursor Clientseitig. Die Lösung mit Kill lässt sich aber als mehr als eine Notlösung implementieren. Ich öffne eine Query mit folgenden Statement:

          SELECT loginame=rtrim(loginame), hostname=rtrim(hostname), spid
          FROM master.dbo.sysprocesses WHERE spid >= 0 and spid <= 32767 AND upper(db_name(dbid)) = 'DBNAME'

          Wenn das Ergebnis nur einen Datensatz enthält und der Login eindeutig der lokalen Maschine zuzuordnen ist, kann ich diese Verbindung guten Gewissens mit 'Kill spid' trennen. Damit ist der Weg frei. Die getrennte Verbindung lässt sich danach auch problemlos wieder öffnen.

          Pete

          Comment

          Working...
          X