I just can't get it when foreignkeys are used

I have read all documentation of Aurelius and XData and I tried the samples, but I miss a good example where a class that references another class (in the database they are connected by foreignkey) is updated. It's no problem to create a class in the server with - say - Name, Addres, Town and fill or update it through XData and Aurelius, but there's always a problem when I have a class with Name, Address, Town and I reference that from another class, for instance Customer. When I call Post(Customer) I always get this:

XData server request error.
Uri: http://localhost:2001/datamodel/customer
Status code: 500
Error Code: EAssociationReferencesTransientObject
Association references a transient object

The whole point is that I don't get how this must be done properly and there is no example and no discription of it in the manuals.

I also miss a good, thorough reference of all the properties and methods of the components and classes used in Aurelius, XData and Sparkle. A good, more complex, example would be nice too. The example you provide with XData (SQLiteConsoleServer) only uses simple classes (no foreignkey connections) and there is no client that uses a TXDataclient provided.

What is your mapping and what is the code you are using in client side.

If you are sending two transient (not saved) objects from client, you must be sure the mapping has cascade save update in that association otherwise server won't save the association automatically (you should do that from the client if that's the case).

This is a part of the Aurelius mapping, generated by the datamodeller from a PostgreSQL database.
I guess there must be something missing?

  [Entity]
  [Table('defadres')]
  [Sequence('defadres_adresid_seq')]
  [Id('Fadresid', TIdGenerator.IdentityOrSequence)]
  Tdefadres = class
  private
    [Column('adresid', [TColumnProp.Required])]
    Fadresid: integer;
    
    [Column('parent', [])]
    Fparent: Nullable<integer>;
   
    [Column('code', [], 30)]
    Fcode: Nullable<string>;
   
    [Column('omschrijving', [], 100)]
    Fomschrijving: Nullable<string>;
  public
    property adresid: integer read Fadresid write Fadresid;
    property parent: Nullable<integer> read Fparent write Fparent;
    property code: Nullable<string> read Fcode write Fcode;
    property omschrijving: Nullable<string> read Fomschrijving write Fomschrijving;
  end;
 
  [Entity]
  [Table('defcustomer')]
  [Sequence('defcustomer_customerid_seq')]
  [Id('Fcustomerid', TIdGenerator.IdentityOrSequence)]
  Tdefcustomer = class
  private
    [Column('customerid', [TColumnProp.Required])]
    Fcustomerid: integer;
   
    [Column('code', [], 30)]
    Fcode: Nullable<string>;
   
    [Column('omschrijving', [], 100)]
    Fomschrijving: Nullable<string>;
   
    [Association([TAssociationProp.Lazy], [])]
    [JoinColumn('adresid', [], 'adresid')]
    Fadresid: Proxy<Tdefadres>;
    function Getafbeeldingid: Tafbeeldingen;
    procedure Setafbeeldingid(const Value: Tafbeeldingen);
    function Getadresid: Tdefadres;
    procedure Setadresid(const Value: Tdefadres);
  public
    property customerid: integer read Fcustomerid write Fcustomerid;
    property code: Nullable<string> read Fcode write Fcode;
    property omschrijving: Nullable<string> read Fomschrijving write Fomschrijving;
    property adresid: Tdefadres read Getadresid write Setadresid;
  end;
 

As I said in my previous post, if you are sending both objects from client (you didn't answer that), you must set save update cascade in association so it also salves Tdefadres when you try to save Tdefcustomer:


 [Association([TAssociationProp.Lazy], [TCascadeType.SaveUpdate])]
    [JoinColumn('adresid', [], 'adresid')]
    Fadresid: Proxy<Tdefadres>;

it's even better to use CascadeTypeAllButRemove

 [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('adresid', [], 'adresid')]
    Fadresid: Proxy<Tdefadres>;

Correct, I did not answer that. When I save a Tdefcustomer, the defadres already exists.
I choose that in the interface from a TList a read from the database earlier by referencing it with a choice made in a combobox:

    defadres: TList<Tdefadres>;
---------
    Comboadres.Clear;
    Try
      defadres:=Client.List<Tdefadres>('$orderby=adresid');
      for nTeller := 0 to defadres.Count-1 do
      begin
        Comboadres.Items.Add(defadres[nTeller].omschrijving);
      end;
    Except
      on E: EWinHttpClientException do
      begin
        FormLog.Log(E.Message);
      end;
    End;
    Comboadres.ItemIndex:=-1;
--------
        defcustomer:=Tdefcustomer.create;
        defcustomer.importid    :=0;
        defcustomer.code        :=EditCode.Text;
        defcustomer.omschrijving:=EditOmschrijving.Text;
        if Comboadres.ItemIndex<0 then defcustomer.adresid:=nil
        else defcustomer.adresid:=defadres[Comboadres.ItemIndex];
        Client.Post(defcustomer);

Thanks. Sorry, I gave you wrong information. The client doesn't have any other way yet to send the data to the server. So you must have the cascade on the server side included, your Post(defcustomer) request will always include the defaddress again (even because client can't tell if you have changed any property) so the cascade is mandatory at server side.

So I have to include this information in the Aurelius mapping on the serverside?

 [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('adresid', [], 'adresid')]
    Fadresid: Proxy<Tdefadres>;

I have the same Unit for server and client. Can I include this on the clientside as well?

Yes

Thank you, Wagner, it works now.