XDATA expose TDynamicProperties from Aurelius model

Hello,

can i expose properties in TDynamicProperties from Aurelius in JSON.
In TDynamicProperties are user defined fields and must be accessed from API

Thank you

Petr

Hello @Petr_Sramek, welcome to TMS Support Center!

Yes, you can use dynamic properties with TMS XData.

Hello @wlandgraf

Thank you for the answer. Can I find an example of how to do this somewhere?

in myApp me use sample code from Aurelius manual like :

procedure TdmAurelius.CreateDynamicProps(ASetup: TMappingSetup);
var  PersonProps: TList<TDynamicProperty>;
begin
    PersonProps := ASetup.DynamicProps[TC_order];
    PersonProps.Add(TDynamicProperty.Create('DynCon', 'GoodBye',
      TypeInfo(string),
      TDynamicColumn.Create('goodbye', [], 30)));

    var mujSQL := dbcontext.GetEmptyUniQuery;
    mujSQL.SQL.Text := 'SELECT * FROM global_settings_user_fields WHERE section=''ZAKAZKY'' AND useInAurelius=1 ORDER BY itemOrder';
    mujSQL.Open;
    begin
       while not mujSQL.eof do
       begin
         if mujSQL.FieldByName('type').AsString='STRING' then
           PersonProps.Add(TDynamicProperty.Create('DynCon', mujSQL.FieldByName('name').AsString,
             TypeInfo(string),
               TDynamicColumn.Create(mujSQL.FieldByName('name').AsString, [], 100)));

         if mujSQL.FieldByName('type').AsString='INT' then
           PersonProps.Add(TDynamicProperty.Create('DynCon', mujSQL.FieldByName('name').AsString,
             TypeInfo(integer),
               TDynamicColumn.Create(mujSQL.FieldByName('name').AsString)));

         if mujSQL.FieldByName('type').AsString='DECIMAL' then
           PersonProps.Add(TDynamicProperty.Create('DynCon', mujSQL.FieldByName('name').AsString,
            TypeInfo(Double),
               TDynamicColumn.Create(mujSQL.FieldByName('name').AsString)));

         if mujSQL.FieldByName('type').AsString='DATE' then
           PersonProps.Add(TDynamicProperty.Create('DynCon', mujSQL.FieldByName('name').AsString,
            TypeInfo(TDate),
               TDynamicColumn.Create(mujSQL.FieldByName('name').AsString)));

         if mujSQL.FieldByName('type').AsString='DATETIME' then
           PersonProps.Add(TDynamicProperty.Create('DynCon', mujSQL.FieldByName('name').AsString,
            TypeInfo(TDatetime),
               TDynamicColumn.Create(mujSQL.FieldByName('name').AsString)));

         mujSQL.Next;
       end;
    end;

end;

procedure TdmAurelius.DefineMappingSetup;
var  MapSetup: TMappingSetup;
begin
  MapSetup := TMappingSetup.Create;
    try
       CreateDynamicProps(MapSetup);
       TMappingExplorer.ReplaceDefaultInstance(TMappingExplorer.Create(MapSetup));
    finally
      MapSetup.Free;
    end;
end;

But if I use this in XData server, server after GET ending with AVE.

I do something wrong. I know.

Thanks Petr

Is it something with Aurelius? Are you able to save and retrieve TC_order entities with the values of dynamic properties properly set?

Once you confirm it's working with Aurelius, then I understand by AVE you mean "Access Violation" you are getting with XData? What is the call stack of the error?

No problem retrieve fields in Aurelius.

AVE = Access Violation. I am sorry, this is localy shortcut.

{
"error": {
"code": "AccessViolation",
"message": "Access violation at address 015BAC6D in module 'VCL_API_Service.exe'. Read of address 00000001"
}
}

image

FDirectSubclasses.Keys inaccessible value

Petr

Can you please provide a minimal compilable sample project reproducing the issue so we can debug and identify the source of the problem?

Yes I can :slight_smile:
DumpSudovo_20240304.zip (333.8 KB)
eMISTRAPIService.zip (430.5 KB)

eMISTRAPIService.zip contain Delphi project
DumpSudovo ... is MariaDB 10.11 dump with specific columns in table c_order

Petr

I cannot execute your SQL dump. Lots of errors.

In any case, this code doesn't look good:

  Explorer := TMappingExplorer.DefaultInstance;
     Model := TXDataAureliusModel.Create(Explorer);
       try
          Builder := TXDataModelBuilder.Create(Model);
             try
               Builder.UseOriginalClassNames := true;
               Builder.UseOriginalFieldNames := true;
               Builder.Build;
             finally
               Builder.Free;
             end;
       except
         Model.Free; // destroy the model in case an error occurs
         raise;
       end;

  ConnectionModule.FireDacMySqlConnection.DefineMappingSetup;

  Module := TXDataServerModule.Create(
    'http://+:8090/Tables',
    TFireDacMySqlConnection.CreatePool(20),Model
  );

You are retrieving the XData model into the Model using the default mapping explorer settings, but only later you call DefineMappingSetup which declares the dynamic properties and replace the existing default explorer.

At this point, the Model was already loaded and that's what you use to create the XData module.

You should create your customize mapping setup before any code that uses it.

Whau. OK i send to you another dump. this dump looks corrupted. Bad format

This is already very experimental code. I added the part with the default model there recently, but didn't thoroughly test it. Then I forgot it was there when I was submitting the example. I'll try to call my own mapping setup before creating the model.

OK i understand what do you mean :slight_smile:

it's easy

 Model := TXDataAureliusModel.Create(Explorer);
 explorer.AddDynamicProperty(Tc_order,TDynamicProperty.Create('DynCon', 'GoodBye',
  TypeInfo(string),
  TDynamicColumn.Create('goodbye', [], 30)));

OMG

Thank you for your time

Petr