Cascade in TList fields

Hello!

I have two classes: TDocument and TDocItem. Here's the code (simplified):

 [Entity]
  [Table('doc_headers')]
  [Id('FId', TIdGenerator.IdentityOrSequence)]
  TDocument = class(TBaseObject)
  private
    [Column('ID')]
    FId: integer;
    ...
    [ForeignJoinColumn('HEADER_ID', [])]
    [ManyValuedAssociation([TAssociationProp.Lazy], CascadeTypeAllRemoveOrphan, 'FDocument')]
    FSpecification: Proxy<TList<TDocItem>>;
    ...
  public
    ...
    property Specification: TList<TDocItem> read GetSpecification write SetSpecification;
  end;


  [Entity]
  [Table('doc_items')]
  [Id('FIndex', TIdGenerator.None)]
  [Id('FDocument', TIdGenerator.None)]
  TDocItem = class(TBaseObject)
  private
    [Column('IDX')]
    FIndex: integer;  <-- This is recalculated before saving the entire TDcoument class

    [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('HEADER_ID', [])]
    FDocument: Proxy<TDocument>;

    [Association([TAssociationProp.Lazy], [])]
    [JoinColumn('PRODUCT_ID', [])]
    FProduct: Proxy<TStockItem>;

    [Column('DESCRIPTION')]
    FDescription: string;
    ...
  public
    ...
    property Idx: integer read FIndex write FIndex;
    property Document: TDocument read GetHeaderId write SetHeaderId;
    property Description: string read FDescription write FDescription;
    ...	
  end;

What is the correct method to:

  1. Save new TDocument, including the TDocItem list
  2. Update existing TDocument classes that also saves/updates TDocItem list (including when you remove an item from the TDocument.Specification list).

Itried with the code like this (simplified), but the TDocItem are not updated when saving/updating TDocument.

  var Doc := TDocument.Create;
  var itm := TDocItem.Create;
  itm.Idx := 1;
  itm.Document := Doc;
  Doc.Specification.Add(itm);

// Saving a new document:
  FManager.Save(Doc);
  FManager.Flush(Doc);

// Updating existing document
  var itm2 := TDocItem.Create;
  itm2.Idx := 2;
  itm2.Document := Doc;
  Doc.Specification.Add(itm2);
  FManager.SaveOrUpdate(Doc);
  FManager.Flush(Doc);

I understood that if I flush just one class, all connected subitems are also saved/updated.

I suspect the problem is in the TDocument class ManyValuedAssociation part, but I can't find how to make it properly work.

Any hint would be appreciated, because I'm stuck here almost a week and is getting frustrating.. :) )

The SaveUpdate cascades cannot work with entities that don’t have automatic generators. The generators are “none”.

This prevents Aurelius from doing proper automatic save/update cascades.

The reason is simple: when you call Save(Doc), it does it correctly, then it will automatically try to save the details.

For each detail, it needs to decide if it’s an INSERT or UPDATE in the database. It does that exactly by checking if the detail object has an id or not. If there is no id, Aurelius generate a new one and performs an INSERT. Otherwise, an UPDATE.

But since you have already set the ID property, Aurelius thinks it needs to do UPDATE, and thus no INSERT is made.

There are two workarounds here:

The only workaround is save master and then manually save each detail.

Ok, thank you!

If I add an unique Id to the detail class, then it will probably work the way I expected, I will try this way also.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.