Frage

Ich habe einen Server mit diesen Codes:

procedure TFrmMain.TCPServerExecute(AContext: TIdContext);
begin
      Res := DoRegister(Name,Family,Username,Password);
end;

function TFrmMain.DoRegister(Name,Family,Username,Password:string): bool;
var
  Qry: TSQLQuery;
begin
  Qry := TSQLQuery.Create(nil);
  try
    Qry.SQLConnection := FrmConnect.SQLConnection;
    Qry.SQL.Text :='INSERT INTO `table` ...';
    Qry.ExecSQL();
  finally
    Qry.Free;
  end;
  Result := True;
end;

ist es irgendein Problem mit Zugriff auf eine Tabelle in verschiedenen Themen? und ganz, was gefährlich ist in dem OnExecute Ereignisse verwendet werden?

Vielen Dank für die Antwort Freunde.

so ist es eine wahre Art und Weise verschiedene Verbindungen für verschiedene Threads zu machen?

var
  Qry: TSQLQuery;
  SqlCon: TSQLConnection;
Begin
  SqlCon := TSQLConnection.Create(nil);
  Qry := TSQLQuery.Create(nil);
  try
    SqlCon := FrmConnect.SQLConnection;
    Qry.SQLConnection := SqlCon;
  finally
    SqlCon.Free;
    Qry.Free;
  end;
end;
War es hilfreich?

Lösung

Ihr zweites Codefragment ist nicht korrekt. Sie überschreiben die neue Verbindung mit dem globalen connect, wenn Sie die Verbindungszeichenfolge kopiert werden sollen. Sie befreit auch, dass die globale was wahrscheinlich Probleme für den Rest der Anwendung verursachen. So etwas wie dies, je nach den Details Ihrer TSQLConnection Klasse:

SqlCon := TSQLConnection.Create(nil); // create
Qry := TSQLQuery.Create(nil);
try
  //SqlCon := FrmConnect.SQLConnection; // overwrite!!!
  SqlCon.ConnectionString :=  FrmConnect.SQLConnection.ConnectionString;
  SqlCon.Active := true;
  Qry.SQLConnection := SqlCon;
  ...

Wenn Sie einen databse Connection-Pool haben wollen ist es ziemlich schwierig, weil die Verbindungen sind in der Regel Thread spezifisch - Sie benötigen eine pro Faden und man kann sich nicht zwischen Threads übergeben. So Sie, dass eine Menge Code zu Unterstützung am Ende zu schreiben.

Ich verwende jetzt die OmniThreadLibrary und haben eine Factory-Methode, dass die Rendite eine neue Datenbankverbindung. Das gibt mir einen Thread-Pool, dass ich Zuführaufgaben in, so dass meine speziellen Aufgabe zu einem bestehenden Thread gebunden, wenn es ausgeführt, aber der Faden ist ziemlich langlebig. Der Code, den ich zu schreiben hatte, dies zu bekommen, ist sehr klein (ich bin mit ADO):

type
    // a factory to generate new instances of our thread-specific data
    IThreadPoolData = interface
        ['{14917B01-6613-4737-B87E-0046789D4284}']
        function GetConnection: TADOConnection;
        function GetStoredProc: TADOStoredProc;
    end;

    TThreadPoolData = class(TInterfacedObject, IThreadPoolData)
    strict private
        FADOConnection: TADOConnection;
        FStoredProc: TADOStoredProc; // lazy creation!
    public
        constructor Create(aConnectionString: string); overload;
        destructor Destroy; override;
        function GetConnection: TADOConnection;
        function GetStoredProc: TADOStoredProc;
    end;

// create the connection here so thread creation is slow but using it 
// is (relatively) fast

constructor TThreadPoolData.Create(aConnectionString: string);
begin
    FADOConnection := TADOConnection.Create(nil);
    FADOConnection.LoginPrompt := false;
    FADOConnection.ConnectionString := aConnectionString;
    FADOConnection.ConnectOptions := coAsyncConnect;
    FADOConnection.Connected := true;
end;

destructor TThreadPoolData.Destroy;
begin
    FADOConnection.Connected := false;
    if assigned(FStoredProc) then
        FreeAndNil(FStoredProc);
    FreeAndNil(FADOConnection);
end;

Sie müssen etwas Ähnliches tun, wenn Sie Ihren eigenen Thread oder Verbindungspool schreiben.

Andere Tipps

Jeder Thread Zugriff auf DB sollte seine eigene Verbindung haben, können Sie keine DB-Verbindung zwischen mehreren Threads gemeinsam nutzen. OnExecute Ereignis wird im Rahmen des Gewindes aufgerufen an den anfordernden Client entspricht, so dass jedes Mal aufgerufen wird, wird es in einem Arbeiter-Thread ausgeführt wird, und ein solcher Faden sollte seine eigenen DB-Verbindung haben.

Wenn Sie nicht wollen, eine neue Verbindung für jeden Worker-Thread schaffen; eine Option sein könnte, können Sie einen einzelnen Thread für DB-Verbindung zu widmen, und delegiert alle DB-Operationen zu diesem Thread, zum Beispiel Ihrer andere Threads ihrer INSERT SQL-Anweisungen in eine Warteschlange in dem DB-Thread senden können, und dass die DB-Thread führt sie ein- by-one mit einer einzigen DB-Verbindung. Natürlich, wenn Sie diesen Ansatz, würde alle DB Last auf einem einzigen Thread, und wenn man so viele DB-Operationen hat, dann, dass die DB fädelt sich eine Performance-Engpass sein könnten! Was mehr ist, diesen Ansatz, Abfrage Hinrichtungen asynchron sein würde, außer Sie eine Synchronisationstechnik verwenden, wenn jeder der Threads den DB-Thread stellen für sie eine DB-Abfrage auszuführen.

beachten Sie auch, dass, wenn Ihr DB Zugriffskomponenten ADO sind, dann müssen Sie CoInitialize und CoUninitialize nennen, weil Delphi Laufzeit nur macht das für den Hauptthread nicht andere Threads, die von Ihnen erstellt werden.

würde ich einen Verbindungspool für die Datenbankverbindungen verwenden. Jeder Thread fordert dann nur eine Verbindung aus dem Pool bei Bedarf (was blockieren könnte, wenn es derzeit keine freien Verbindungen im Pool ist) und dann verwendet und schließlich gibt es an den Pool. Ein Pool hat den Vorteil, dass es weniger Verbindungen benötigt, als es gleichzeitige Threads, und die Verbindungen sind bereits vorhanden, wenn nötig.

Ja und nein. Sie können aus unterschiedlichen Threads einer einzigen Tabelle zugreifen, aber Sie müssen eine TSQLConnection Instanz pro Thread so sicher zu machen.

Aktualisieren

eine andere Verbindung für jeden Thread Instanziierungsanwendung ist in Ordnung. Es ist, was die meisten Webseiten tun die ganze Zeit als auch (Server Side Scripting mit ASP, PHP oder ... Mittel Zustand lose Ausführung und damit in der Regel Verbindungen nicht auf die nächste Anforderung überleben und haben wieder hergestellt sein).

Wenn Sie über den Kopf besorgt sind, können Sie mit einer einzigen Verbindung prüfen, wie vcldeveloper vermuten läßt. Sie müssen, um sicherzustellen, dass alle Variablen und Mitgliedsfelder von diesem „Verbindungsfaden“ verwendet, die von den anderen Threads geändert werden (zum Beispiel des Feldelement der SQL Empfangen ausgeführt werden), durch eine Art von Synchronisationsmechanismus geschützt werden müssen .

Das gleiche gilt für den Verbindungspool wie mjustin vorgeschlagen, obwohl in diesem Fall der Verbindungspool Bedürfnisse durch Synchronisationsmechanismen geschützt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top