Mydac connection data base issue

drama22
drama22 used Ask the Experts™
on
i have a server that client connect To .   each client on server have its own mydac TMyConnection. but every time new client connect to server old clients have the new client data base which is wrong step here is my server code

type
  TConnection = class(TIdServerContext)
  private
    // WriteLock: TCriticalSection;
    dbconnect: TMyConnection;

  public
    OutboundCache: TIdThreadSafeStringList;
    Name: String;
    Databasename : string;

    constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn;
      AList: TIdContextThreadList = nil); override;
    destructor Destroy; override;


constructor TConnection.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn;
  AList: TIdContextThreadList = nil);
begin
  inherited;
  // WriteLock := TCriticalSection.Create;
  OutboundCache := TIdThreadSafeStringList.Create;
  dbconnect := TMyConnection.Create(nil);
  dbconnect.Pooling := true;
  dbconnect.PoolingOptions.Validate := true;
  dbconnect.Server := 'localhost';
  dbconnect.username := 'root';
  dbconnect.Password := 'password';
  dbconnect.ConnectionTimeout := 0;
  connectionmo.userslq.Connection := dbconnect;
end;

destructor TConnection.Destroy;
var
  Cache: TStringList;
  I: integer;
begin
  // WriteLock.Free;
  if OutboundCache <> nil then
  begin
    Cache := OutboundCache.Lock;
    try
      for I := 0 to Cache.Count - 1 do
        Cache.Objects[I].Free;
    finally
      OutboundCache.Unlock;
    end;
    OutboundCache.Free;
  end;
  inherited;
end;

Open in new window


Server execute


procedure TServobj.TcpServerExecute(AContext: TIdContext);
var
  Connection: TConnection;
  Command: String;
  Params: array [1 .. 200] of String;
  Cache, OutboundCmds: TStringList;
  ParamsCount, P: integer;
  MS: TMemoryStream;
  copiedMS: TMemoryStream;
  ReceiveParams, ReceiveStream: BOOLEAN;
  Size: Int64;
  I: integer;
  S: String;
begin
  Connection := AContext as TConnection;

  // check for pending outbound commands...
  OutboundCmds := nil;
  try
    Cache := Connection.OutboundCache.Lock;
    try
      if Cache.Count > 0 then
      begin
        OutboundCmds := TStringList.Create;
        OutboundCmds.Assign(Cache);
        Cache.Clear;
      end;
    finally
      Connection.OutboundCache.Unlock;
    end;

    if OutboundCmds <> nil then
    begin
      for I := 0 to OutboundCmds.Count - 1 do
      begin
        AContext.Connection.IOHandler.Writeln(OutboundCmds.Strings[I],
          IndyTextEncoding_UTF8);
        MS := TMemoryStream(OutboundCmds.Objects[I]);
        if MS <> nil then
        begin
          AContext.Connection.IOHandler.LargeStream := true;
          AContext.Connection.IOHandler.Write(MS, 0, true);
        end;
      end;
    end;
  finally
    if OutboundCmds <> nil then
    begin
      for I := 0 to OutboundCmds.Count - 1 do
        OutboundCmds.Objects[I].Free;
    end;
    OutboundCmds.Free;
  end;

  // check for a pending inbound command...
  if AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    AContext.Connection.IOHandler.CheckForDataOnSource(100);
    AContext.Connection.IOHandler.CheckForDisconnect;
    if AContext.Connection.IOHandler.InputBufferIsEmpty then
      Exit;
  end;

  Command := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
  // read command

  if Command = '' then
    Exit;

  ReceiveParams := False;
  ReceiveStream := False;

  if Command[1] = '1' then // command with params
  begin
    Command := Copy(Command, 2, MaxInt);
    ReceiveParams := true;
  end
  else if Command[1] = '2' then // command + memorystream
  begin
    Command := Copy(Command, 2, MaxInt);
    ReceiveStream := true;
  end
  else if Command[1] = '3' then // command with params + memorystream
  begin
    Command := Copy(Command, 2, MaxInt);
    ReceiveParams := true;
    ReceiveStream := true;
  end;

  if ReceiveParams then // params is incomming
  begin
    S := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
    ParamsCount := 0;
    while (S <> '') and (ParamsCount < 200) do
    begin
      Inc(ParamsCount);
      P := Pos(Sep, S);
      if P = 0 then
        Params[ParamsCount] := S
      else
      begin
        Params[ParamsCount] := Copy(S, 1, P - 1);
        Delete(S, 1, P + 4);
      end;
    end;
  end;

  MS := nil;
  try
    if ReceiveStream then // stream is incomming
    begin
      MS := TMemoryStream.Create;
      AContext.Connection.Socket.LargeStream := true;
      AContext.Connection.Socket.ReadStream(MS, -1, False);
      MS.Position := 0;
    end;

if Command = 'TAKEINFO' then // login ok, add to listview
    begin
      Connection.Name := Params[1];
      Connection.Databasename := Params[2]; //database from client side

    end

else if Command = 'LST' then
    begin
      Connection.LST(Params[1]); // Params[1] equals to data base name that sent from client side
    end;

  finally
    MS.Free;
  end;

procedure TConnection.LST(DATABASENAME: string);
var
  LVU: TStringList;
  memorylist: TMemoryStream;
begin
  // collect
TThread.Synchronize(nil,
procedure
begin
try
  dbconnect.Database := DATABASENAME;
  dbconnect.Connect;
// collect rooms
begin
 try
 LVU := TStringList.Create;
 with connectionmo.userslq do
 begin
 Close;
 SQL.Clear;
 SQL.Add('SELECT * FROM `Data`');
 Open; // open the query
 try
 while not Eof do
 begin
 LVU.Add(
 connectionmo.userslq.FieldByName('username').AsString + Sep
 );
 Next;
 end;
 finally
 Close;
 end; // end LVU
 end;

 // sendlist
 if (LVU.Count > 0) then
 begin
 memorylist := TMemoryStream.Create;
 try
 LVU.SaveToStream(memorylist);
 memorylist.Position := 0;
 Self.SendCommandAndStream('LST', memorylist); // send list back to client
 finally
 memorylist.Free;
 end;
 end;
 finally
 LVU.Free;
 end;
 end;
 // sync end

 finally
 dbconnect.Disconnect;
 end;

end);
end;

Open in new window



code works  and send list but issue is like this example

lets say old client has connected to the server with data base "Fine" and requested list with this data base he received it normally

but if new client connected to server with different data base for example "LOG" and old client request data base "Fine" he receive Database "LOG" of New client  what could be the issue ? do i setup the data base connection right ? what i need is gives each client his own database to get data From .
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Software architect
Top Expert 2012
Commented:
Never share connection between threads. It would be the best if you could create query/dataset connection inside thread. Example ... ado components are good for this because connection can be create by simple connection string.

TConnection = class(TIdServerContext)
  private
...
end;

procedure TConnection.LST(DATABASENAME: string);
var
  LVU: TStringList;
  memorylist: TMemoryStream;
  qry:TADOQuery;
begin
  LVU := TStringList.Create;
  try
    qry:=TADOQuery.Create(Self);
    try
      try
        qry.ConnectionString:=<conn string using DATABASENAME>;
        qry.SQL.Text:='SELECT * FROM `Data`';
        qry.CursorType:=ctOpenForwardOnly;
        qry.LockType:=ltReadOnly;
        qry.DisableControls;
        qry.Open;
  
        while not qry.Eof do
        begin
           LVU.Add(qry.FieldByName('username').AsString + Sep;
          qry.Next;
        end;
      finally
        qry.Close;
        qry.Free;
     end;
   ///send goes here ....
  except
  end;
finally
  LVU.Free;
end;
....

Open in new window

Author

Commented:
Thank you sinisa is this thread safe by the way ?
Sinisa VukSoftware architect
Top Expert 2012

Commented:
Yes....

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial