Asynchrone LoadData

I have an entity TPerson and a lazy association to TPersonMemos. (Master/Detail)
One Person has many memos. The loadingprocess is too slow to load the memo data immediately.


I use Omnithread Library. How can I load the memos?

Here are my code for loading the Person:


function TdmPerson.LoadPerson(APersonID: TGuid; AJobNum: Integer; ACallback: TModelCallbackEvent): Boolean;
begin
  Async(
    procedure begin
      FPerson := XClient.Get<TPerson, TGuid>(APersonID);
    end)
  .Await(
    procedure begin
      if assigned(ACallback) then
        if FPerson <> nil then
          ACallback( self, AJobNum, GUIDToString( FPerson.PersonID))
        else
          ACallback( self, AJobNum, '');
    end);
end;


And what can I do for Memos


function TdmPerson.LoadPersonMemo( APersonID: TGuid; AJobNum: Integer; ACallback: TModelCallbackEvent): Boolean;
begin
  Async(
    procedure begin
      FPerson.PersonMemoList. := XClient. ... ???
    end)
  .Await(
    procedure begin
      if assigned(ACallback) then
        // Do something
    end);
end;


I don't want to change the data. I will only show the memos.

How is your mapping? Is PersonMemoList lazy load (proxy) or not?
If it's lazy load, you can simply read the property:

function TdmPerson.LoadPersonMemo( APersonID: TGuid; AJobNum: Integer; ACallback: TModelCallbackEvent): Boolean;
begin
  Async(
    procedure begin
      FPerson.PersonMemoList:
    end)
  .Await(
    procedure begin
      if assigned(ACallback) then
        // Do something
    end);
end;

It works, but I get an exception at point 3

1:  FPerson.PersonMemoList;


2: function TPerson.GetPersonMemoList: TList<TPersonMemo>;
begin
  result := FPersonMemoList.Value;
end;

3: (in unit Aurelius.Types.Proxy;)
function Proxy<T>.GetValue: T;
begin
  // No need to check for FLoaded, just optimization
  if not FLoaded then Load;
  Result := FValue;
end;

Here is the mapping:



  [Entity]
  [Table('t_p_person')]
  [Id('FPersonID', TIdGenerator.None)]
  TPerson = class
  private
    [Column('p_id', [TColumnProp.Required])]
    FPersonID: TGuid;
    
--->   Here some other columns    
    
    [ManyValuedAssociation([TAssociationProp.Lazy, TAssociationProp.Required], [TCascadeType.SaveUpdate, TCascadeType.Merge, TCascadeType.Remove], 'FPersonID')]
    FPersonMemoList: Proxy<TList<TPersonMemo>>;
    
    function GetPersonMemoList: TList<TPersonMemo>;
  public
    constructor Create;
    destructor Destroy; override;
    property PersonID: TGuid read FPersonID write FPersonID;
    property PersonMemoList: TList<TPersonMemo> read GetPersonMemoList;
  end;



  [Entity]
  [Table('t_p_memo')]
  [Id('FPersonMemoID', TIdGenerator.None)]
  TPersonMemo = class
  private
    [Column('pm_id', [TColumnProp.Required])]
    FPersonMemoID: TGuid;
    
    [Column('pm_memo', [], 32000)]
    FMemo: Nullable<string>;
    
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('p_id', [TColumnProp.Required], 'p_id')]
    FPersonID: Proxy<TPerson>;
    function GetPersonID: TPerson;
    procedure SetPersonID(const Value: TPerson);
  public
    property PersonMemoID: TGuid read FPersonMemoID write FPersonMemoID;
    property Memo: Nullable<string> read FMemo write FMemo;
    property PersonID: TPerson read GetPersonID write SetPersonID;
  end;




I think, the fault is because I use a thread.

I have no inits and the only line code is to call PersonMemoList in Thread-Execute (Async-Proc)

How OTL works:

I call a procedure in "Async" (this is the thread) and if it ends the lines in "Await" are executed;

The proxy uses the same XClient object to load the proxied list. You must be sure XClient object is still "alive" (not destroyed) by the time FPerson.PersonMemoList is called.

Yes, the xClient is still alive.

My mistake was here:
I loaded the person and the memos almost simultaneously

Calling the LoadPersonMemo after person isLoaded and all is working fine


procedure TffKunde.Init;
begin
  inherited;
  pvm := TPersonViewmodel.Create;
  pvm.OnLoadPerson := PersonGeladen;
  pvm.LoadPerson( StringToGUID( InputValue.AsString));
  pvm.LoadPersonMemo;
end;


Thank you, for all your work, Wagner.