Delphi Clinic C++Builder Gate Training & Consultancy Delphi Notes Weblog Dr.Bob's Webshop
Bob Swart (aka Drs.Bob) Dr.Bob's Delphi Clinics Dr.Bob's Delphi Courseware Manuals
View Bob Swart's profile on LinkedIn Drs.Bob's Delphi Notes
These are the voyages using Delphi Enterprise (and Architect). Its mission: to explore strange, new worlds. To design and build new applications. To boldly go...
Title:

Sharing VCL data modules with VCL for the Web

Author: Bob Swart
Posted: 2/20/2008 4:52:50 PM (GMT+1)
Content:

Tomorrow in my free seminar, I'll show - among others - how to share your data modules in a VCL Win32 / .NET and a VCL for the Web application. First of all, I assume you have an existing VCL application that uses data modules (with database connections, queries, stored procedures, business rules, etc).
One of the big advantages of VCL for the Web (aka IntraWeb) is the fact that you can reuse existing VCL data modules, as part of the UserSessionUnit.

The trick is as follows: in your project group that contains the VCL application (with the data module), create a new VCL for the Web application, and make sure to check the "Create User Session" option, so a UserSessionUnit.pas file is created with your project as well:




When the new VCL for the Web project is created, right-click on the project target and select Add... to add a new file to the project.
In the dialog that follows, select the VCL data module from your existing VCL project.

Then, check the main project file and make sure the code to automatically create the data module is removed (since we cannot have just one data module, but we must have one for each incoming request):
  //Application.CreateForm(TDataModule1, DataModule1);
This is the first step in sharing the single data module in both the VCL Win32 / .NET and the VCL for the Web application.

Once the VCL data module is added to your VCL for the Web project, open the UserSessionUnit.pas file.
Press Alt+F11 to make sure the VCL data module is added to the uses clause of the UserSessionUnit.pas unit.

Note that inside the UserSessionUnit unit, the TIWUserSession class is already derived from a TIWUserSessionBase and represented as a data module.
However, this is not the data module you want to use, since that won't allow you to share your business logic between the VCL Win32 / .NET and VCL for the Web application.
Instead, we should add a field to the TIWUserSession for your data module, and implement a constuctor of the TIWUserSession that will create the data module, as follows:
  type
TIWUserSession = class(TIWUserSessionBase)
private
{ Private declarations }
public
{ Public declarations }
MyDataModule: DataMod.TDataModule1;
constructor Create(AOwner: TComponent); override;
end;
The implementation of the constructor is as follows:
  constructor TIWUserSession.Create(AOwner: TComponent);
begin
inherited
;
MyDataModule := DataMod.TDataModule1.Create(Self);
end;
This is the second step, but we're not done yet.
In our VCL for the Web Forms, we obviously want to connect to the DataModule at design-time, and don't want to write complex code to connect to the UserSession.MyDataModule.whatever datasets and fields.

For this, we usually use the global DataModule1 instance variable in the data module unit, declared as follows:
var
DataModule1: TDataModule1;
However, that's not a good idea in this case, since there can be many instances of the data module (which is likely since the VCL for the Web application will receive many incoming requests, each having a User Session with a unique instance of the Data Module).
So using the global variable is a no-no here.

Instead, we should change this to a function that will return the specific field from the UserSession, as follows:
(*$IFDEF IW*)
function DataModule1: TDataModule1;
(*$ELSE*)
var
DataModule1: TDataModule1;
(*$ENDIF*)
And now we need to implement that function in the implementation section of the Data Module, as follows:
implementation
(*$IFDEF IW*)
uses
ServerController, UserSessionUnit;

...

function DataModule1: TDataModule1;
begin
Result := UserSession.MyDataModule
end;
(*ENDIF*)
Now, we can add the Data Module unit to the uses clause of our IntraWeb Forms, and use the tables, queries, dataset and data sources in our IntraWeb code.
Just make sure to define IW when compiling the VCL for the Web edition of the data module, and remove that define when you compile the regular Win32 or .NET version.

The best way is to define IW in the "Conditional defines" box of the Project Options for the IntraWeb application, so it's only used in that case (beware that you still need to do a Build All if you switch from one project to another, since the Conditional define is not identified as a change in source code by the compiler; but that's another issue).

Back  


11 Comments

AuthorPostedComments
Arwing 08/07/03 14:26:27In last code snippet (*ENDIF*) will get you: [DCC Error] DataModule.pas(27): E2280 Unterminated conditional directive Use (*$ENDIF*) instead ;)
Bob Swart 08/07/29 17:20:39You are right, thanks for the notice - the actual code is correct ;-)
Fred Lima 10/07/16 16:03:10Hi, there is an error in your code it is not (*ENDIF*) missing a $ before E
Ederson Selvati 10/08/18 22:58:24Hi Do I need to do this for all datamodules in my application? I have many business classes in my project, this does not leave the software slow?
Bob Swart 10/08/19 09:36:18You don't have to do this for all data modules if you don't want to: you can also dynamiclaly create them as fields in the UserSession if you want.
Vinicius Matos 10/08/25 21:14:28Hy i done what you said but no work Error on execute the program : Error message raised by the application: Resource TDataModule1 not found afther this line : MyDataModule := datamodule.TDataModule1.Create(Self); that is in this function in usersessionunit constructor TIWUserSession.Create(AOwner: TComponent); begin inherited; MyDataModule := datamodule.TDataModule1.Create(Self); end; thanks
Bob Swart 10/08/25 22:57:16"Resource TDataModule1 not found" sounds like you're missing an include of a .dfm file perhaps? I'm not sure if that's an IntraWeb issue...
Danilo Casa 10/12/29 08:58:33Hi, this article is very interesting... You said that "you can also dynamically create them as fields in the UserSession": but can I create a datamodule as a field of a form? The main question is: do datamodules have to be declared in UserSession?
Bob Swart 10/12/29 12:25:25You can create a data module as a field of a form as well if you want.
Bob Swart 12/11/20 23:06:05This and more is covered in my Delphi IntraWeb courseware manual, see http://www.drbob42.com/Courseware for more details.
the best seo service 13/09/06 19:57:43okY8Ew Major thanks for the article post.Thanks Again. Fantastic.


New Comment (max. 2048 characters, no HTML):

Name:
Comment:



This webpage © 2005-2017 by Bob Swart (aka Dr.Bob - www.drbob42.com). All Rights Reserved.