Question

J'ai un serveur avec ces 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;

est-il un problème avec l'accès à une table dans diverses discussions? et ce qui est tout à fait dangereux pour être utilisé en cas OnExecute?

Merci pour les amis de réponse.

, est-il un vrai moyen de faire des liens différents pour différents threads?

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;
Était-ce utile?

La solution

Votre deuxième fragment de code est incorrect. Vous écrasez la nouvelle connexion avec la connexion globale, lorsque vous devez copier la chaîne de connexion. Vous libérant ainsi également que mondiale qui sera probablement causer des problèmes pour le reste de votre application. Quelque chose comme ça, selon les détails de votre classe TSQLConnection:

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;
  ...

Si vous voulez avoir un pool de connexion databse il est assez délicat car les connexions sont thread spécifiques généralement - vous avez besoin d'un par fil et vous ne pouvez pas les passer entre les fils. Donc, vous finissez par écrire beaucoup de code à l'appui.

Je vais maintenant utiliser le OmniThreadLibrary et ont une méthode de fabrication qui retourne une nouvelle connexion de base de données. Cela me donne un pool de threads que je nourris des tâches dans, donc ma tâche spécifique est liée à un fil existant lors de l'exécution, mais le fil est assez long vécu. Le code que je devais écrire pour obtenir ce qui est très petit (j'utilise 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;

Vous aurez besoin de faire quelque chose de similaire si vous écrivez votre propre piscine de fil ou connexion.

Autres conseils

Chaque thread accès DB doit avoir sa propre connexion, vous ne pouvez pas partager une connexion DB entre plusieurs threads. OnExecute événement est invoqué dans le contexte du fil correspondant au client demandeur, donc à chaque fois qu'il est appelé, il est exécuté à l'intérieur d'un thread de travail, et un tel fil doit avoir sa propre connexion DB.

Si vous ne voulez pas établir une nouvelle connexion pour chaque thread de travail; une option pourrait être, vous consacrez un seul fil pour la connexion DB et déléguer toutes les opérations de DB à ce fil, par exemple vos autres threads peuvent envoyer leurs instructions INSERT SQL à une file d'attente dans ce thread DB, et que le fil DB les exécute ONe par une en utilisant une seule connexion DB. Bien sûr, si vous prenez cette approche, toute la charge de DB serait sur un seul thread, et si vous avez tant d'opérations de DB, alors que DB fil lui-même pourrait être un goulot d'étranglement! De plus, cette approche, les exécutions de requête seraient asynchrones, sauf que vous utilisez une technique de synchronisation chaque fois que chacun de vos fils demander le fil DB pour exécuter une requête DB pour eux.

Veuillez également prendre note que si vos composants d'accès DB sont ADO, vous devez appeler CoInitialize et CoUninitialize, car l'exécution Delphi fait seulement pour le thread principal pas les autres fils qui sont créés par vous.

J'utiliser un pool de connexion pour les connexions de base de données. Chaque thread demande alors qu'une connexion de la piscine en cas de besoin (ce qui pourrait bloquer si des connexions sont actuellement pas libres dans la piscine), puis utilise et retourne finalement à la piscine. Une piscine a l'avantage qu'il ya moins de connexions nécessaires que il y a des threads simultanés, et les connexions sont déjà présentes en cas de besoin.

Oui et non. Vous pouvez accéder à une seule table à partir de fils différents, mais vous avez besoin d'une instance de TSQLConnection par thread de le faire en toute sécurité.

Mise à jour

Instantiating une connexion différente pour chaque fil est fin. Il est ce que la plupart des pages Web font tout le temps aussi bien (script côté serveur en utilisant asp, php ou ... des moyens d'exécution de l'état moins et donc les connexions ne survivent habituellement pas à la demande suivante et doivent être mis en place re-).

Si vous êtes inquiet au sujet de la surcharge, vous pouvez envisager d'utiliser une seule connexion comme vcldeveloper suggère. Vous devrez veiller à ce que toutes les variables et les champs membres utilisés par ce « fil de connexion » qui sont changés par les autres threads (par exemple l'organe de champ recevant le SQL à exécuter), devront être protégés par une sorte de mécanisme de synchronisation .

est de même pour le pool de connexion tel que suggéré par mjustin, bien que dans ce cas, les besoins du pool de connexions à être protégées par des mécanismes de synchronisation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top