Jump to content
Sign in to follow this  
borni69

delphimvcframework global variable

Recommended Posts

Hi ,

I have downloaded the delphimvcframework and it look’s great 🙂 thanks to  @Daniele Teti , I have also bought the book 🙂 great reading, recommended. 

I love this system , but will play more with it next couple of weeks.

 

A small question.

 

We have a small webbroker app  today running on Apache AWS, we use a globale Dict as a keystore in all requests, and we use FMX data pooling.

FMX data pooling seems to be well documented in your book, and I guess I can almost use like before.  

 

If you look at below code we use dict String_Dict as a global variable handled by

TMultiReadExclusiveWriteSynchronizer, any suggestion where to put his variable in delphimvcframework to be able to use it in the different controller / actions

like FMVC.AddController(TCustomersController);


 

In our webmodule we have a global variable and we use it with TMultiReadExclusiveWriteSynchronizer from system.sysutil

 

Example data from from our Webmodule

 

…
public
    { Public declarations }
    SettingTemplateClass : TSettingTemplateClass;
end:


var
  WebModuleClass: TComponentClass = TWebModule1;

  String_Dict      : TDictionary<string,String > ;
  string_Dict_Sync : TMultiReadExclusiveWriteSynchronizer;


…..
// connecting String_Dict to a setting class unique for each request

procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
  SettingTemplateClass := TSettingTemplateClass.Create
  SettingTemplateClass.string_Dict_Sync   := string_Dict_Sync;
  SettingTemplateClass.String_Dict        := String_Dict;
….
end;

// a typical request  sending  string_dict further  using settingTemplateClass to the class generating the response via usersession class
procedure TWebModule1.WebModule1getlogondataAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
 userSession      : TuserSession;
 ssoInternalClass  : TssoInternalClass;
 companyid        : Integer;
 lsession_data    : String;

begin

 companyid      := strtointdef( getRequestParamValue (Request , 'companyid' ),0);
 userSession := TuserSession.create(SettingTemplateClass,getRequestParamValue(request,'token'));

  try
    if isSessionValid(Response,userSession) then
    begin
       lsession_data :=getRequestParamValue (Request , 'session_data' );
       userSession.userSessionData.setSessionData(lsession_data);

       ssoInternalClass  := TssoInternalClass.Create(userSession);
       try
          Response.content  :=  ssoInternalClass.getLogonData( companyid  );
       finally
         ssoInternalClass.Free;
       end;
    end;
  finally
   userSession.Free;
  end;

end;

…………

initialization

  String_Dict      := TDictionary<string,String >.create ;
  string_Dict_Sync := TMultiReadExclusiveWriteSynchronizer.Create;


finalization

  String_Dict.Free;
  string_Dict_Sync.Free;

Example using string_dict in class generating the response data below .

 

 

 string_Dict_Sync.BeginRead;
    try
      string_Dict.TryGetValue('severDayNumberString',  severDayNumberString );
    finally
     string_Dict_Sync.EndRead;
    end;

 

 

It it possible o do something similar with delphimvcframework,   ?

For me it seems like difficult to share data to a controller .. 

Thanks in advance

Edited by borni69

Share this post


Link to post

Yes, you can use this in delphimvcframework. I declare such dictionary in the service unit (it's a windows service), or you can put it in a datamodule and create it at program start and destroy at the end. Webmodule can be created and destroyed several times during program execution.

Share this post


Link to post
3 hours ago, Alberto Fornés said:

Yes, you can use this in delphimvcframework. I declare such dictionary in the service unit (it's a windows service), or you can put it in a datamodule and create it at program start and destroy at the end. Webmodule can be created and destroyed several times during program execution.

Thanks, I can create it in a datamodule, but I still do not understand howto get this datamodule all the way down to the controller..

 

FMVC.AddController(TCustomersController);

 

Tcustomercontroller is a class created on request  ,and the dict is created at startup.

 

I undestand that I can use/create a datamodule in the controller, but not howto use one created at startup, holding all the data,, normally I would send the dict to my class using a variable.

procedure TMyController.GetCustomers ;
  var 
   lCustomersModule : TMyDataModule ; 
    begin 
     lCustomersModule := TMyDataModule . Create ( nil ) ; 
      try 
       lCustomersModule . QryCustomers . Open () ; 

 

again thanks

 

  I will also try a few options myself...

Edited by borni69

Share this post


Link to post
36 minutes ago, borni69 said:

Thanks, I can create it in a datamodule, but I still do not understand howto get this datamodule all the way down to the controller..

 

FMVC.AddController(TCustomersController);

 

Tcustomercontroller is a class created on request  ,and the dict is created at startup.

 

I undestand that I can use/create a datamodule in the controller, but not howto use one created at startup, holding all the data,, normally I would send the dict to my class using a variable.


procedure TMyController.GetCustomers ;
  var 
   lCustomersModule : TMyDataModule ; 
    begin 
     lCustomersModule := TMyDataModule . Create ( nil ) ; 
      try 
       lCustomersModule . QryCustomers . Open () ; 

 

again thanks

 

  I will also try a few options myself...

No , this datamodule should be created at start, and always alive, you reference it from your controller (add datamodule unit to controller), and access it through TMultiReadExclusiveWriteSynchronizer.

Share this post


Link to post
12 minutes ago, Alberto Fornés said:

No , this datamodule should be created at start, and always alive, you reference it from your controller (add datamodule unit to controller), and access it through TMultiReadExclusiveWriteSynchronizer.

OKI  thanks alot 🙂

Share this post


Link to post
21 hours ago, borni69 said:

OKI  thanks alot 🙂

This is my result from test..  and it seems to work..

 

unit HseqDmDictU;

interface

uses
  System.SysUtils, System.Classes,  Generics.collections;

type
  TDataModuleDict = class(TDataModule)
  private
    FString_Dict: TDictionary<string, String>;
    Fstring_Dict_Sync: TMultiReadExclusiveWriteSynchronizer;
    procedure SetString_Dict(const Value: TDictionary<string, String>);
    procedure Setstring_Dict_Sync(
      const Value: TMultiReadExclusiveWriteSynchronizer);
    { Private declarations }
  public
    { Public declarations }

    destructor Destroy; override;
    procedure initDict;

    property  String_Dict      : TDictionary<string,String >  read FString_Dict write SetString_Dict;
    property  string_Dict_Sync : TMultiReadExclusiveWriteSynchronizer read Fstring_Dict_Sync write Setstring_Dict_Sync;


  end;

var
  DataModuleDict: TDataModuleDict;


implementation

{%CLASSGROUP 'System.Classes.TPersistent'}

{$R *.dfm}


{ TDataModuleDict }

procedure TDataModuleDict.initDict;
begin
    FString_Dict      := TDictionary<string,String >.create ;
    Fstring_Dict_Sync := TMultiReadExclusiveWriteSynchronizer.Create;
end;

destructor TDataModuleDict.Destroy;
begin
    FString_Dict.Free;
    Fstring_Dict_Sync.Free;

  inherited;
end;

procedure TDataModuleDict.SetString_Dict(
  const Value: TDictionary<string, String>);
begin
  FString_Dict := Value;
end;

procedure TDataModuleDict.Setstring_Dict_Sync(
  const Value: TMultiReadExclusiveWriteSynchronizer);
begin
  Fstring_Dict_Sync := Value;
end;

end.

 

On my console app startup init the Datamodule  (not sure for Linux where I will put it, but will try later)

 

begin
  ReportMemoryLeaksOnShutdown := True;
  IsMultiThread := True;
  // Prepare Dict
  DataModuleDict:= TDataModuleDict.Create(nil);
  try
     DataModuleDict.initDict;  // Important
      try
        if WebRequestHandler <> nil then
          WebRequestHandler.WebModuleClass := WebModuleClass;
        WebRequestHandlerProc.MaxConnections := 1024;
        RunServer(8080);
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;


  finally

    DataModuleDict.Free;

  end;


end.

 

Using dict in code from  seperate unit 

 

unit DictU;

interface
uses
   system.sysutils , system.classes ,DataConU,
   Generics.collections ,  TemplateRecordU;

 type
    TDictClassV2 = Class ( Tobject )
     private

     public
      procedure   saveString         ( akey   , avalue : String ) ;
      function    loadString         ( akey            : String ) :String;

    End;

implementation

uses HseqDmDictU;

{ TDictClassV2 }

function TDictClassV2.loadString(akey: String): String;
begin
 result:='';
  DataModuleDict.string_Dict_Sync.BeginRead;
 try
   DataModuleDict.string_Dict.TryGetValue(akey,result);
 finally
   DataModuleDict.string_Dict_Sync.EndRead;
 end;



end;

procedure TDictClassV2.saveString(akey, avalue: String);
begin
  DataModuleDict.string_Dict_Sync.BeginWrite;
     try
      try
        if not DataModuleDict.String_Dict.ContainsKey(akey) then
            DataModuleDict.String_Dict.Add(akey,avalue);
       Except
          on E : Exception do
         begin
              // logg error
         end;
      end;
     finally
       DataModuleDict.string_Dict_Sync.EndWrite;
     end;


end;

end.

 

If you would do it differently please let me know  Thanks again...

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

Ă—