Hoe kan ik in een DataSnap (MIDAS) applicatieserver gebruik maken van meerdere Remote DataModules?

Als je een standaard DataSnap appserver maakt lijkt het inderdaad de bedoeling dat je alle datasets op één remote datamodule plaatst. In een wat groter project is dat natuurlijk niet handig omdat het niet mogelijk is met meerdere programmeurs aan de server te programmeren en de verzameling datasets wordt slecht onderhoudbaar.

Delphi 6 heeft een mogelijkheid om meerdere remote datamodules in één server te plaatsen. Er wordt een object factory gemaakt waarin de classes zijn geregistreerd en vanuit deze factory worden de RDM's aangemaakt. Je maakt dus een nieuwe RDM en geeft deze bijvoorbeeld de interface IChild. Vervolgens voeg je een property aan je hoofdinterface toe die de IChild retourneert. Voor iedere Child RDM maak je een eigen factory aan en in de GetMethod van deze property zet je de code om de client aan te maken. Je MainRDM ziet er dan als volgt uit:

Code:
unit MainRDMU;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
  DBClient, RDMServer_TLB, StdVcl;

type
  TMainRDM = class(TRemoteDataModule, IMainRDM)
  private
    FChild1Factory: TComponentFactory;
    FChild2Factory: TComponentFactory;
  protected
    class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
    function Get_Child1: IChildRDM1; safecall;
    function Get_Child2: IChildRDM2; safecall;
  public
  end;

implementation

uses ChildRDM1u, ChildRDM2u;

{$R *.DFM}

class procedure TMainRDM.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
  if Register then
  begin
    inherited UpdateRegistry(Register, ClassID, ProgID);
    EnableSocketTransport(ClassID);
    EnableWebTransport(ClassID);
  end else
  begin
    DisableSocketTransport(ClassID);
    DisableWebTransport(ClassID);
    inherited UpdateRegistry(Register, ClassID, ProgID);
  end;
end;

function TMainRDM.Get_Child1: IChildRDM1;
begin
  if not Assigned(FChild1Factory) then
    FChild1Factory :=
      TComponentFactory.Create(ComServer, TChildRDM1, Class_ChildRDM1,
                               ciInternal, tmApartment);
  Result := FChild1Factory.CreateCOMObject(nil) as IChildRDM1;
end;

function TMainRDM.Get_Child2: IChildRDM2;
begin
  if not Assigned(FChild2Factory) then
    FChild2Factory :=
      TComponentFactory.Create(ComServer, TChildRDM2, Class_ChildRDM2,
                               ciInternal, tmApartment);
  Result := FChild2Factory.CreateCOMObject(nil) as IChildRDM2;
end;

initialization
  TComponentFactory.Create(ComServer, TMainRDM,
    Class_MainRDM, ciMultiInstance, tmApartment);
end.
Vervolgens zet je op je client voor iedere Child RDM een SharedConnection die je, via je DCOMConnection koppelt aan de verschillende ChildRDM's. Aan de shared connections koppel je vervolgens je ClientDataSets.

Je hoofd RDM op de server fungeert nu als 'doorgeefluik' voor je verschillende Child RDM's en je DComConnection op je client fungeert weer als 'doorgeefluik' naar je verschillende SharedConnections.

In de bijgesloten ZIP heb ik een testproject gemaakt om e.e.a. te laten zien.