HttpAPI TRoComplexType Create and Free

HI,

I want to confirm the suggested way on create and free TROComplextype on HttpAPI custom server.
Delphi 10.3.3 , DA 10.0.0.1463 , CodeFirstServer.

  TKB_AVFSInfo = class;
  TKB_AVFSInfoArray = class;


  TKBInfo = class(TROComplexType)
  private
    fEngName : String;
    fKB_DT  : TDateTime;
    FKB_Files: TKB_AVFSInfoArray;
  published
    [ROSerializeAsAnsiString]
    property EngName: String read fEngName write fEngName;
    property KB_DT: TDateTime read fKB_DT write fKB_DT;
    property KB_Files: TKB_AVFSInfoArray read  FKB_Files  write  FKB_Files;
  end;


  TKB_AVFSInfo = class(TROComplexType)
  private
    fFilePath : String;
    fKB_AVFS_GUID: String;
  published
    [ROSerializeAsAnsiString]
    property FilePath: String read fFilePath write fFilePath;
    property KB_AVFS_GUID: String read fKB_AVFS_GUID write fKB_AVFS_GUID;
  end;

  TKBInfoArray = class(TROArray<TKBInfo>);
  TKB_AVFSInfoArray = class(TROArray<TKB_AVFSInfo>);

This is the RODLTypes.

[ROServiceMethod]
[ROCustom('HttpApiPath','kblist')]
 function GetKBList(const TRD_CONTENT: UnicodeString;): TKBInfoArray;



function TDataService.GetKBList(const TRD_CONTENT: UnicodeString): TKBInfoArray;
var
  srcData,dataKey: IDADataset;
  i,nStart,nEnd,nFirst: integer;
  wb:TDAWhereBuilder;
  p:TKBInfo;
  aExp1: array of TDAWhereExpression;
  kbfiles:TKB_AVFSInfoArray;
  afvsfile : TKB_AVFSInfo;
  sNewID:String;

begin
  result := TKBInfoArray.Create;
  sNewID:='';
  srcData:=Schema.NewDataset(Connection,'kb_file_view',[],wb.Xml);
  srcData.Open;
  while Not srcData.Eof do
  Begin
if sNewID<>srcData.FieldByName('KB_ID_PK').AsString then
Begin
 kbfiles:=TKB_AVFSInfoArray.Create;
  p := Result.Add();
End;
p.EngName :=  srcData.FieldByName('KB_NAME_ENG_LNG').AsString;
p.KB_DT := srcData.FieldByName('KB_DT').AsDateTime;


 p.KB_Files := kbfiles;
 afvsfile := kbfiles.Add();
 afvsfile.FilePath :=   srcData.FieldByName('afvs_file').AsString;
 afvsfile.KB_AVFS_GUID := srcData.FieldByName('afvs_guid').AsString;

 sNewID:=srcData.FieldByName('KB_ID_PK').AsString;
 srcData.Next;

  End;
  srcData := Nil;
  dataKey:= Nil;
  FreeAndNil(wb);
end;

The above code is running perfect . However, I concern any memory leaking.

As I create each TKB_AVFSInfoArray for each TKBInfo
, also I create TKB_AVFSInfo for each TKB_AVFSInfoArray.

Any Memory leakage in above code?

As the general from the doc, service side no need free and resource as RO will handle.
I checked other thread add afterconstructor and BeforeDestructor to free and nil the resource for those client in written in delphi.

Once I added below code, the server show invalid pointer operation

procedure TKBInfo.AfterConstruction;
begin
  inherited;
FKB_Files:=TKB_AVFSInfoArray.Create;
end;

procedure TKBInfo.BeforeDestruction;
var i:Integer;
    p : TKB_AVFSInfo;
begin
  inherited;
 for i := 0 to FKB_Files.Count-1 do
Begin
    p :=  FKB_Files[i];
    FreeAndNil(p);
  End;
  FKB_Files.Clear;
  FreeAndNil(FKB_Files);
end; 

please advise what is the way to handle or what the issue on above code.

Hi,

using another struct/array inside struct is a bit tricky part in CodeFirst services.

I’d recommend to declare your struct inside ServiceBuilder and review how to it will be generated.

for example, array inside struct:

  NewStruct = class(TROComplexType)
  private
    fNewField: NewArray;
    function GetNewField: NewArray;
  protected
    property int_NewField: NewArray read fNewField;
    procedure FreeInternalProperties; override;
  public
    procedure Assign(aSource: TPersistent); override;
    procedure ReadComplex(aSerializer: TObject); override;
    procedure WriteComplex(aSerializer: TObject); override;
  published
    property NewField: NewArray read GetNewField write fNewField;
  end;
...
function NewStruct.GetNewField: NewArray;
begin
  if not assigned(fNewField) then begin
    fNewField := NewArray.Create();
  end;
  result := fNewField;
  exit;
end;

procedure NewStruct.FreeInternalProperties;
begin
  FreeOrDisposeOf(fNewField);
end;

as you can see, it will create create array in GetNewField and destroy it in FreeInternalProperties. also this code doesn’t generate memory leaks.