Domanda

ho un server con questi codici:

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;

c'è qualche problema con l'accesso a una tabella in varie discussioni? e totalmente ciò che è pericoloso per essere utilizzato in caso OnExecute?

Grazie per gli amici di risposta.

è così, è un vero e proprio modo per effettuare le connessioni diverse per le diverse discussioni?

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;
È stato utile?

Soluzione

Il secondo frammento di codice non è corretto. Stai sovrascrivendo il nuovo collegamento con la connessione globale, quando si dovrebbe essere copiando la stringa di connessione. Sei anche liberando quella globale che sarà probabilmente causare problemi per il resto della vostra applicazione. Qualcosa di simile, a seconda dei dettagli della vostra 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;
  ...

Se si desidera avere un pool di connessione databse è abbastanza difficile perché i collegamenti sono di solito specifiche thread-- è necessario uno per filo e non è possibile passare tra i thread. Così si finisce per scrivere un sacco di codice per supportare questo.

Ora utilizzare il OmniThreadLibrary e hanno un metodo factory che restituisce una nuova connessione al database. Questo mi dà un pool di thread che mi nutro attività in, quindi il mio compito specifico è associato a un thread esistente quando si esegue, ma il filo è abbastanza a lungo vissuto. Il codice che ho dovuto scrivere per ottenere questo è molto piccolo (sto usando 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;

Sarà necessario fare qualcosa di simile, se si scrive il proprio pool di thread o connessione.

Altri suggerimenti

Ogni thread accesso DB dovrebbe avere il proprio collegamento, non è possibile condividere una connessione DB tra diversi thread. OnExecute evento viene richiamato nel contesto del filo corrispondente al client richiedente, per cui ogni volta che viene invocato, viene eseguito all'interno di un thread di lavoro, e tale filo dovrebbe avere il proprio connessione DB.

Se non si desidera stabilire una nuova connessione per ogni thread di lavoro; una soluzione potrebbe essere, di dedicare un singolo thread per il collegamento di DB, e delegare tutte le operazioni di DB a quel filo, ad esempio i vostri altri thread possono inviare le loro dichiarazioni INSERT SQL per una coda in quel filo DB, e che DB thread esegue li con una o by-one utilizzando una singola connessione DB. Naturalmente se si prende questo approccio, tutto il carico di DB sarebbe su un singolo thread, e se si hanno tante operazioni di DB, allora che DB infilare per sé potrebbe essere un collo di bottiglia! Cosa c'è di più, questo approccio, le esecuzioni di query sarebbero asincrona ad eccezione si utilizza una tecnica di sincronizzazione ogni volta che ciascuno dei vostri filetti chiedere il filo DB per eseguire una query DB per loro.

Anche prendere atto che se i componenti di accesso DB sono ADO, allora dovete chiamare CoInitialize e CoUninitialize, perché Delphi runtime fa solo che per il thread principale non altri thread che vengono creati da voi.

I userebbe un pool di connessione per le connessioni al database. Ogni filo quindi richiede solo una connessione dal pool quando necessario (che potrebbe bloccare se non ci sono attualmente connessioni non libero in piscina) e quindi utilizza e, infine, lo restituisce al pool. Una piscina ha il vantaggio che ci sono meno connessioni necessarie che ci sono thread concorrenti, e le connessioni sono già presenti quando necessario.

Sì e no. È possibile accedere a una singola tabella da diversi thread, ma è necessario un esempio TSQLConnection per thread di farlo in modo sicuro.

Aggiorna

Instantiating una connessione diverse per ogni filo è soddisfacente. E 'quello che la maggior parte delle pagine web fanno tutto il tempo così (di scripting lato server utilizzando ASP, PHP o ... mezzi di esecuzione allo stato di meno e quindi le connessioni di solito non sopravvivono alla successiva richiesta e devono essere ristabilito).

Se siete preoccupati per il sovraccarico, è possibile considerare l'utilizzo di una singola connessione come vcldeveloper suggerisce. Si dovrà garantire che tutte le variabili ei campi utente utilizzati da tale "filettatura" che vengono cambiati dagli altri fili (ad esempio l'elemento di campo riceve lo SQL da eseguire), dovranno essere protetti da una sorta di meccanismo di sincronizzazione .

Lo stesso vale per il pool di connessioni come suggerito da mjustin, anche se in tal caso, le esigenze del pool di connessione siano protetti da meccanismi di sincronizzazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top