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