How to use TSessions for database access in INDY HTTP SERVER

I would just like to know the right way to do this:

MY APPLICATION:
1.      i am using delphi 7
2.      i made a web server application using the INDY HTTP SERVER component.
3.      everytime a client accesses the web server application, the application will have to access and update a firebird database (odbc), which is done inside the OnCommandGet event of the IdHTTPServer; Here, many users may access the database simultaneously.
4.      i believe that the right way to do this is by using database sessions (TSession).

QUESTIONS:
1.      As this application is multithreaded were clients may connect simultaneously, could a datamodule containing queries and stored procedures (created at design time) be used with unique DATABASE sessions (TSession)?
2.      OR, should we just create a new DATABASE session (TSession) and the databases, queries and stored procedures components dynamically (runtime) in the OnCommandGet event in the IdHTTPServer?
3.      In the OnCommandGet event, should the database be opened everytime a client connects with a new HTTP session?
4.      In the OnCommandGet event, should the database be closed after processing and giving a response to the client?
5.      Or should the database be closed only when the client ends the HTTP session?
6.      When do we free the TSessions created?

NOTE: the HTTP SESSION is different from the database TSESSION

You may answer my questions by giving me a DELPHI SAMPLE CODE.

Thank you very much for your help,
Syndman
syndmanAsked:
Who is Participating?
 
TheRealLokiConnect With a Mentor Senior DeveloperCommented:
oops, should be
tbBioLife.SessionName := 'Session_' + IntToStr(UniqueID); // the same as we made for the TSession

so I think for Indy HTTP server, it would look something like this :-

// our session with the TSession, and tables needed by the web session
type
  TMyHTTPSession = class(TIdHTTPSession)
  private
    Session_ForThisThread: TSession;
    tbBioLife: TTable;
  end;


procedure TForm1.IdHTTPServer1CreateSession(ASender: TIdContext; var VHTTPSession: TIdHTTPSession);
begin
    VHTTPSession := TMyHTTPSession.Create(IdHTTPServer1.SessionList);
end;

procedure TForm1.IdHTTPServer1SessionStart(Sender: TIdHTTPSession);
begin
    if (Sender is TMyHTTPSession) then
    with (Sender as TMyHTTPSession) do
    begin
        Session_ForThisThread := TSession.Create(nil);
        Session_ForThisThread.SessionName := 'Session_' + SessionID;
        Session_ForThisThread.Active := True;

        tbBioLife := TTable.Create(nil);
        tbBioLife.DatabaseName := 'DBDEMOS';
        tbBioLife.SessionName := 'Session_' +SessionID;
        tbBioLife.TableName := 'biolife.db';
    end;
end;

procedure TForm1.IdHTTPServer1SessionEnd(Sender: TIdHTTPSession);
begin
    if (Sender is TMyHTTPSession) then
    with (Sender as TMyHTTPSession) do
    begin
        tbBioLife.Free;
        Session_ForThisThread.Free;
    end;
end;
0
 
TheRealLokiSenior DeveloperCommented:
You are correct.
For a multithreaded environment (which is what your web sessions are) you need to use a different TSession for each.
If your web session created a TDatamodule, you could use the TSessions's AutoSessionName property. If it doesn't (which is more likely the case) you should make up your own sessionname. You will need a unique name, perhaps some web session id, or similar.

Personally, I would create the TSession dynamically when the web session starts, and free it when the web session ends.
as an example, I will also create a TTable here

    var
{this needs to be in the web session, and accessible for the whole thread}
        Session_ForThisThread: TSession;
        tbBioLife: TTable;
        i: integer; // just for example
        s: string; // just for example
    begin
{create the session and necessary tables
note: you can not use "AutoSessionName" if you have more than 1 TSession on this
form/datamodule, so we will use a UniqueID that is passed in the creation of this web session, and
will be available for thei thread only.}
        Session_ForThisThread := TSession.Create(nil);
        Session_ForThisThread.SessionName := 'Session_' + IntToStr(UniqueID);
        Session_ForThisThread.Active := True;

        tbBioLife := TTable.Create(nil);
        tbBioLife.DatabaseName := 'DBDEMOS';
        tbBioLife.SessionName := 'Session_UniqueID';
        tbBioLife.TableName := 'biolife.db';

        tbBioLife.Open;
        for i := 0 to pred(tbBioLife.FieldCount) do
          s := s + tbBioLife.Fields[i].AsString; // just an example
        tbBioLife.Close;

{destroy the TSession and TTable when the web session/thread is destroyed}
        tbBioLife.Free;
        Session_ForThisThread.Free;
    end;
0
 
syndmanAuthor Commented:
TheRealLoki,
Thanks for your very comprehensive reply.
May I know your email address.
Thanks again,
Syndman
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
syndmanAuthor Commented:
TheRealLoki,
Oh, you are one of the top experts here.
Thanks again,
Syndman
0
 
TheRealLokiSenior DeveloperCommented:
no problem. lokiwashere at yahoo co nz
0
 
syndmanAuthor Commented:
thanks again
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.