Master/Detail

I have a master/Detail relationship mapped as follows:

  [Entity]
  [Table('TBLREZEPT')]
  [Id('FREZEPTID', TIdGenerator.None)]
  TTBLREZEPT = class
  private
    [Column('REZEPTID', [TColumnProp.Required, TColumnProp.NoUpdate])]
    FREZEPTID: Integer;
   
    [ManyValuedAssociation([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll , 'FREZEPTID')]
    FTBLREZEPTZUTATList: Proxy<TList<TTBLREZEPTZUTAT>>;
  public

and 

  [Entity]
  [Table('TBLREZEPTZUTAT')]
  [Id('FREZEPTID', TIdGenerator.None)]
  [Id('FREZEPTPOSID', TIdGenerator.None)]
  TTBLREZEPTZUTAT = class
  private
    [Column('REZEPTPOSID', [TColumnProp.Required, TColumnProp.NoUpdate])]
    FREZEPTPOSID: Integer;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('REZEPTID', [TColumnProp.Required], 'REZEPTID')]
    FREZEPTID: Proxy<TTBLREZEPT>;

This is a legacy DB, so I provide the IDs myself Prior to inserting the records.

Adding is no Problem:
SAVE the REZEPT
add and save each ZUTAT:
                      Zutat := TTblrezeptzutat.Create;
                      Zutat.REZEPTPOSID := uc.GetNextID('tblrezeptzutat.rezeptposid');
                      mgrManager.Save(Zutat);
                      Rezept.TBLREZEPTZUTATList.Add(Zutat);


However, when I want to update the REZEPT, i first want to delete all ZUTAT:

          for Zutat in Rezept.TBLREZEPTZUTATList do begin
            mgrManager.Remove(Zutat);
          end;

The DELETE Statements are created and executed.

However, adding fails:
                      Zutat := TTblrezeptzutat.Create;
                      Zutat.REZEPTPOSID := uc.GetNextID('tblrezeptzutat.rezeptposid');
                      mgrManager.Save(Zutat); < --------------------- ERROR

Im Projekt RezeptSchnittstelle.exe ist eine Exception der Klasse EMappingNotFound mit der Meldung 'Cannot find mapping [Id] on class "nil".' aufgetreten.

This is weird, because without the removing, this works ok.

Any idea?

When you remove the objects, make sure to also remove the Zutat objects from the parent list. Otherwise the list will reference destroyed objects.

Alternatively, you can use

mgrManager.DeferDestruction := True;

to prevent removed objects from being destroyed until the object manager itself is destroyed.
>make sure to also remove the Zutat objects from the parent list.

This is the list of the parent: Rezept.TBLREZEPTZUTATList.
Do you mean remove, removeitem or delete?

Something like this:


          for Zutat in Rezept.TBLREZEPTZUTATList do begin
            Rezept.TBLREZEPTZUTATList.Remove(Zutat);
            mgrManager.Remove(Zutat);
          end;
Ok, thanks for that. I'll give it a try.

But I am unsure - why does this not work?
  for Zutat in Rezept.TBLREZEPTZUTATList do begin
            Rezept.TBLREZEPTZUTATList.Remove(Zutat);
          end;
mgrManager.Flush(Rezept);

Because it destroys the Zutat objects.

Then you can Flush(Rezept) but the Rezept object holds a list of the destroyed Zutat objects, which are inspected by Flush. When Flush tries to examine such destroyed objects, the AV is raised.

I see. Tx!