#1 2019-04-29 22:29:16

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

[MVC] Best pratices to Access ORM inside service

Hi guys,


I would like some suggestions on how best to access ORM inside a service that is not registred with main server ...

In my case I need to disable external access to the ORM so I have a TSQLRestServerFullMemory server created and started with MVC application.


  //A "Dummy" server to avoid UI access to ORM
  FDummyServer := TSQLRestServerFullMemory.Create(TSQLModel.Create([],'test'),False);
  FDummyServer.ServiceRegister(TMyService,[TypeInfo(IMyService)],sicShared);

  inherited Start(FDummyServer,TypeInfo(ITestApplication));

  fMainRunner := TMVCRunOnRestServer.Create(Self);

  FHTTPServer := TSQLHttpServer.Create('8080',FDummyServer,useHttpApiRegisteringURI);
  FHTTPServer.RootRedirectToURI('test/default');
  FDummyServer.RootRedirectGet := 'test/default';


  //My real server with access to ORM
  FInternalRestModel := TSQLRestServerDB.Create(CreateModel,ChangeFileExt(ExeVersion.ProgramFileName,'.db'), False);
  FInternalRestModel.DB.Synchronous := smNormal;
  FInternalRestModel.DB.LockingMode := lmExclusive;
  FInternalRestModel.CreateMissingTables;

And this interface.

  IMyService = interface(IInvokable)
    ['{E956F65D-7FAE-4BDD-9210-111E088284F5}']
    function MyResponse(const MyString: RawUTF8): RawUTF8;
  end;

  TMyService = class(TInjectableObjectRest, IMyService)
    function MyResponse(const MyString: RawUTF8): RawUTF8;
  end;

...

function TMyService.MyResponse(const MyString: RawUTF8): RawUTF8;
begin
 ...
  Self.Server  <- Point to "Dummy" server TSQLRestServerFullMemory 
  I need access to FInternalRestModel (TSQLRestServerDB) 
end;

How to access the real server inside this services without breaking some framework design principle?

Last edited by macfly (2019-04-29 22:30:44)

Offline

#2 2019-04-29 23:02:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: [MVC] Best pratices to Access ORM inside service

For sicShared, the easiest is to just use ServiceRegister() and provide a TMyService instance with its dependencies injected, instead of just specifying the TMyService class and letting the framework create the instance.

Offline

#3 2019-04-30 01:10:26

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: [MVC] Best pratices to Access ORM inside service

Thanks ab!

Offline

#4 2019-04-30 19:17:42

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: [MVC] Best pratices to Access ORM inside service

Just to take the doubt...

Since TSQLRestServer classes are not implemented with injectable interfaces, I need to create a intermediary class, for this, rigth?

Or is there a direct way?

Intermediary class to inject the restserver:

  IMyRestInject = interface(IInvokable)
    ['{XYZ...}']
    function GetRestModel : TSQLRestServerDB;
    property RestModel : TSQLRestServerDB read GetRestModel;
  end;

  TMyRestInject = class(TInterfacedObject, IMyRest)
  protected
    FRestModel : TSQLRestServerDB;
  public
    constructor Create(ARestModel : TSQLRestServerDB);
    function GetRestModel : TSQLRestServerDB;
  end;
TMyService = class(TInjectableObjectRest, IMyService)
private
  FRest: IMyRestInject;
public
  function MyResponse(const MyString: RawUTF8): RawUTF8;
published
  property Rest: IMyRestInject read FRest write FRest;
end;

function TMyService.MyResponse(const MyString: RawUTF8): RawUTF8;
begin
  Result := Self.Rest.RestModel.DB.FileName; //uses injected restserver
end;

Application Startup

 ...
  FModel := CreateModel;
  FInternalRestModel := TSQLRestServerDB.Create(FModel,ChangeFileExt(ExeVersion.ProgramFileName,'.db'), False);
  FInternalRestModel.DB.Synchronous := smNormal;
  FInternalRestModel.DB.LockingMode := lmExclusive;
  FInternalRestModel.CreateMissingTables;

  FDummyServer := TSQLRestServerFullMemory.Create(TSQLModel.Create([],'test'),False);

  //Created to inject FInternalRestModel  
  AMyRestInject := TMyRestInject.Create(FInternalRestModel);

  AMyService := TMyService.CreateInjected([],[],[AMyRestInject ]);

  FDummyServer.ServiceRegister(AMyService,[TypeInfo(IMyService)]);

Last edited by macfly (2019-04-30 19:18:52)

Offline

#5 2019-05-01 06:50:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: [MVC] Best pratices to Access ORM inside service

You are confusing interfaces and class injection.
If you inject a TSQLRestServerDB via a constructor parameter, no need to use interface injection.

No need to create an intermediate class anyway, in your use case.
Interface injection is a good idea only if you define your sub-services as dependencies, and want to mock/stub them, or use a remote service.

Offline

#6 2019-05-01 17:19:35

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: [MVC] Best pratices to Access ORM inside service

You're right.

This code became redundant.
The idea would be to put all the dependencies in this interface ..

But instantiating directly is actually better and simpler.

Thanks

Offline

Board footer

Powered by FluxBB