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).
|