Quantcast
Viewing all articles
Browse latest Browse all 18

Sharing DB connection between multiples DataSnap Server Modules

When developers starts creating Delphi DataSnap application it is very common to see the database connection defined per Data Module. Doing this will generate a lot of connections on the database, and depending on the situation it will became a problem.

In Delphi XE, DataSnap introduce the Session Management that will make easy to implement the control on the server side to manage the database connection for the clients. The client application won’t know anything about that, the server will do the magic.

When we create a DataSnap Server it is best practice to define a Server Container (Data Module), which contains the DataSnap Server component and registers all the server classes required by the application. In this container we will define the method responsible for dealing with the database connections for each Server Class.

As an example, I have implemented a GetConnection method on the Server Container. This method is responsible for assigning the connection looking in to the connection pool, which will a have list of connections per client.

  private
    { Private declarations }
    ListofConnection : TDictionary;
  public
    function GetConnection : TSQLConnection;

In case the server receives new requests from new clients the GetConnection will create a new connection and add to the pool list. If the client already have a connection associated, the GetConnection will just return a instance of SQLConnection. The pool uses the Thread ID to control the unique connection per client. If you use DataSnap 2010 you have to use the method GetThreadSession for this purpose.

function TServerContainer1.GetConnection: TSQLConnection;
var
  dbconn : TSQLConnection;
begin

  if ListofConnection.ContainsKey(TDSSessionManager.GetThreadSession.Id) then
     Result := ListofConnection[TDSSessionManager.GetThreadSession.Id]
  else
  begin
    dbconn := TSQLConnection.Create(nil);
    dbconn.Params.Clear;
    dbconn.LoadParamsOnConnect := true;
    dbconn.ConnectionName := 'DS Employee';

    ListofConnection.Add(TDSSessionManager.GetThreadSession.Id, dbconn);
    Result := dbconn;
  end;

end;

Since the connection is defined we need to update all datasets to use this connection, as well the server methods that create and execute SQL queries at run-time will have to invoke the GetConnection.

If you are using the VCL Data components (TSQLQuery, TSQLStoredProc, etc…) on your Server DataModules, the onCreate event is a good place to associate the DataSets with the connection, using the following code.

procedure TServerContainer1.SetConnection(Conn: TSqlConnection);
var
  i: integer;
begin
  if Conn = nil then
     Conn := GetConnection;
  else
    Conn := Sender;

  for i := 0 to ComponentCount - 1 do
    if Components[i] is TSQLQuery then
       TSQLQuery(Components[i]).SQLConnection := Conn;
end;

To avoid connection leaks on the database, we implement the onDisconnect event from DSServer. This will be executed when the client disconnects.

  if GetConnection <> nil then
     GetConnection.Close;

The source code is available for download at Code Central.

Related Posts

Andreano Lanusse | Technology and Software Development
Follow me on Twitter: @andreanolanusse


Viewing all articles
Browse latest Browse all 18

Trending Articles