Icon View Thread

The following is the text of the current message along with any replies.
Messages 21 to 30 of 41 total
Thread 1000 Databases With 64 Datasets Each Crashes The EWB Server
Fri, Aug 10 2018 11:05 AMPermanent Link

Frederick Chin

Raul wrote:

/*
Sure - nothing really changes here except your module dynamically
connects to appropriate database on the backend (invisibly to EWB).
*/

Can you point me to some example project/code that I can refer to create the web module?

I am using Delphi 10 Seattle and I am totally lost as to what to do. What kind of project should I be creating?

--
Frederick
Sat, Aug 11 2018 12:24 PMPermanent Link

Frederick Chin

Uli,

/*
If you have several databases defined in EDB, this would be a possible
approach:

1. Name all databases "DBCustomer" + CustomerID
2. Create a login in EWB and after getting back the CustomerID, store
this ID in memory and use it for all requests (using a module off course)
3. In the module uses something like this:

procedure TDataSetModule.EWBModuleExecute(Request: TEWBServerRequest);
var
   CurrentCustomerID: string;
   CurrentDatabaseName: string;
begin
   CurrentCustomerID := RequestParams.Values['CustomerID'];
   CurrentDatabaseName := 'DBCustomer' + CurrentCustomerID;
   MyEDBDatabase.Database := CurrentDatabaseName;
   ...
end;
*/

I've reviewed your suggestion above and the key point is that I will need multiple databases defined. For example, if I needed 100 databases, I would need DBCustomer001 to DBCustomer100. Like you said, it is not the way to do it.

Since I use DBISAM, I tried using a trial version of DBISAM with Rad Studio 10s. The database component of DBISAM holds promise because I can define the directory name based on the database name the module receives. However, when I drop a TDatabase component of DBISAM on to the EWB module and tried to compile the module, Rad Studio complains about missing dbisamcn, dbisamen, dbisamsq, dbisamlb DCU files plus tons of other Undeclared Identifier errors when it compiles DBISAMTB.PAS. Quite messy.

If the compilation should eventually work, I will add the following:-

procedure TDataSetModule.EWBModuleExecute(Request: TEWBServerRequest);
var
   CurrentCustomerID: string;
   NewDir : String;
begin
   CurrentCustomerID := RequestParams.Values['CustomerID'];
   if CurrentCustomerID='001' then
      NewDir:='dir1'
   else if CurrentCustomerID='002' then
      NewDir:='dir2'
   else
      // <and so on>
   MyDBISAMDatabase.Directory := NewDir;
end;

In my EWB application, I will set

MyDatabase.BaseURL:='databasemodules/mydbmodule';


Do you think the above will work?

--
Frederick
Sat, Aug 11 2018 12:26 PMPermanent Link

Frederick Chin

Frederick Chin wrote:

/*
Can you point me to some example project/code that I can refer to create the web module?

I am using Delphi 10 Seattle and I am totally lost as to what to do. What kind of project should I be creating?
*/

Scratch the above. I now know how to create the module but I am stuck with coding.

--
Frederick
Sat, Aug 11 2018 2:52 PMPermanent Link

Uli Becker

Frederick,

> I've reviewed your suggestion above and the key point is that I will need multiple databases defined. For example, if I needed 100 databases, I would need DBCustomer001 to DBCustomer100. Like you said, it is not the way to do it.

You talked about defining 1000 databases in *EWB*. That's not what I
said. If you define your databases in *EDB* or even simpler with DBISAM,
you need just one database instance in your module and switch to the
according database of your customer depending of his ID. The whole thing
happens on the server.

And in *EWB* you need to define just your 64 datasets (independent of
the database).

Hope that helps.

Uli
Sat, Aug 11 2018 6:26 PMPermanent Link

Uli Becker

As for the trial version of DBISAM you'll need to compile with runtime packages. At least that's the case with EDB.

Uli
Sat, Aug 11 2018 8:03 PMPermanent Link

Frederick Chin

Uli,

/*
You talked about defining 1000 databases in *EWB*. That's not what I
said. If you define your databases in *EDB* or even simpler with DBISAM,
you need just one database instance in your module and switch to the
according database of your customer depending of his ID. The whole thing
happens on the server.

And in *EWB* you need to define just your 64 datasets (independent of
the database).
*/

Thanks. I'll explore this further.

--
Frederick
Sun, Aug 12 2018 5:44 AMPermanent Link

Ronald

Hi Frederick,

I had the same problem and worked it out like this. It resembles the advice you already got.
The "excecmain" procedure does the actual reading and saving of the .
I can send you that too if that helps.
The databasemodule is called "gdba" (gdba.dll)


procedure TgdbaModule.EWBModuleExecute(Request: TEWBServerRequest);
var
UserNo,UserRole                                      :string;
LocalSession                                         :TDBISAMSession;
LocalDatabase                                        :TDBISAMDatabase;
LocalQuery                                           :TDBISAMQuery;
begin
  try
  LocalSession:=GetNewSession;
     try
     LocalDatabase:=TDBISAMDatabase.Create(nil);
        try
        LocalDatabase.SessionName:=LocalSession.SessionName;
        LocalDatabase.DatabaseName:=Request.RequestParams.Values['database'];
        LocalDatabase.Directory:=DatabaseBaseDir+'\'+LocalDatabase.DatabaseName;
        LocalDatabase.Connected:=True;
        LocalQuery:=TDBISAMQuery.Create(nil);
           try
           LocalQuery.SessionName:=LocalSession;
           LocalQuery.DatabaseName:=LocalDatabase;

           SetUpQueryTable(LocalSession,LocalDatabase,LocalQuery);
           GetUserPermissions(Request,LocalDatabase,LocalQuery,UserNo,UserRole);
           if UserNo='' then raise Exception.Create('Uw inloggegevens zijn niet correct, log in en probeer het opnieuw. (1)');
           ExecMain(Request,LocalDatabase,LocalQuery,UserRole);

           finally
           LocalQuery.Free;
           end;
        finally
        LocalDatabase.Free;
        end;
     finally
     LocalSession.Free;
     end;
  except
  on e:exception do
     begin
     AddToSysLog('gdbamoduleexecute:'+e.Message,GetSysLogName(Request.RequestParams.Values['database']));
     Request.SendError(HTTP_BAD_REQUEST,KillPaths(e.Message));
     end;
  end;
end;

function GetNewSession: TDBISAMSession;
begin
SessionNameSection.Enter;
  try
  LastSessionValue:=LastSessionValue+1;
  Result:=TDBISAMSession.Create(nil);
  with Result do SessionName:='AccountSession'+IntToStr(LastSessionValue);
  finally
  SessionNameSection.Leave;
  end;
end;


In the client I do this:

Database.BaseURL:='/databasemodules/gdba'; //the name of the module on your server, I placed this in the "databasemodules" directory in the root of your directory at the server
tbSampleTable.Params.Clear;
tbSampleTable.DataSetName:='adatasetname';  //in the module I use this as the actual name of the sql script
tbSampleTable.Open;
Database.LoadRows(tbSampleTable);


Greetings,
Ronald
Sun, Aug 12 2018 7:52 AMPermanent Link

Frederick Chin

Hi Ronald,

/*
I had the same problem and worked it out like this. It resembles the advice you already got.
The "excecmain" procedure does the actual reading and saving of the .
I can send you that too if that helps.
The databasemodule is called "gdba" (gdba.dll)
*/

Thank you very much for your help. I tried your code as-is but there are quite a lot of "Undeclared Identifiers". I've managed to condense your code to a compilable portion as follows:-

procedure TgdbaModule.EWBModuleExecute(Request: TEWBServerRequest);
var
  LocalDatabase : TDBISAMDatabase;
  cCustomerid : String;
begin
  LocalDatabase:=TDBISAMDatabase.Create(nil);
  try
     cCustomerID:=Request.RequestParams.Values['customerid'];
     LocalDatabase.Directory:='c:\datalist\db'+cCustomerID;

     // What should I have here so that the calling EWB client will know the directory of the new database

  finally
     LocalDatabase.Free;
  end;
end;

The "customerid" value is obtained by the EWB client after a successful login and the idea is that the TDatabase's DatabaseName will be assigned a new database with the "customerid" suffixed and the EWB client will then know which directory the new database points to.

For example, if I receive a customer ID of 002, I will assign "DB002" to the database and the module will check the directory for 002 and return a directory of C:\DATALIST\DB002 to the EWB client.

--
Frederick
Sun, Aug 12 2018 10:03 AMPermanent Link

Ronald

Frederick Chin wrote:

<
procedure TgdbaModule.EWBModuleExecute(Request: TEWBServerRequest);
var
  LocalDatabase : TDBISAMDatabase;
  cCustomerid : String;
begin
  LocalDatabase:=TDBISAMDatabase.Create(nil);
  try
     cCustomerID:=Request.RequestParams.Values['customerid'];
     LocalDatabase.Directory:='c:\datalist\db'+cCustomerID;

     // What should I have here so that the calling EWB client will know the directory of the new database

  finally
     LocalDatabase.Free;
  end;
end;
>

You can not create a database this way. This is not thread safe. You need to read this:

https://www.elevatesoft.com/manual?action=viewtopic&id=dbisam4&product=delphi&version=5&topic=multi_threaded_applications

In my apps I have set name of the database encrypted in the query that I give to the customer so the client know which database to use. In the actual call to the server the name is visible of course, but that is not a securityissue because you need to be authenticated before you can

Ronald
Sun, Aug 12 2018 10:08 AMPermanent Link

Ronald

When I copied my source, I tried to compact it and I made a mistake:

It should be:

LocalQuery.SessionName:=LocalSession.SessionName;
LocalQuery.DatabaseName:=LocalDatabase.DatabaseName;

Ronald
« Previous PagePage 3 of 5Next Page »
Jump to Page:  1 2 3 4 5
Image