RemoveOrphan on Master-Detail

Hi,
  When Flushing a single object (Master-Detail), the TCascadeType.RemoveOrphan does not
RemoveOrphan.
  thanks
 

Please provide detailed info: current mapping and code used. Have you also added TCascadeType.Flush to the association?

yes i added TCascadeType.Flush to the Many-Valued Association.
...
  fAssociation := aMappingExplorer.GetAssociationByPropertyName(TInvoice, 'InvoiceItemsList');
  if fAssociation <> nil then
    fAssociation.Cascade := fAssociation.Cascade + [TCascadeType.Flush];
...
Typical case Saving a Invoice(Master) and InvoiceItems(Detail).

More, cascadeFlush simple does not save InvoiceItems when Save Invoice Object with single Object and CascadeFlush , but should?
thanks

Please provide the complete mapping and code you are using to remove the associated orphan and flushing it. You should have CascadeType.SaveUpdate and Flush.

"You should have CascadeType.SaveUpdate and Flush"
 CascadeType: [SaveUpdate,Merge,Remove,RemoveOrphan,Flush]

Ok, here is an extract from the code

To generate initial Schema I use Data Modeler. However for options not availabel in Data Modeler,
 i add it by code, like:
   ...
   class procedure AddCascadeRemoveOrphan(aMappingExplorer: TMappingExplorer; aClassName: TClass; aPropName: String); //Used for Many-Valued Association
   class procedure AddOrderManyValuedAssociation(aMappingExplorer: TMappingExplorer; aMasterClassName: TClass; aMasterPropName: String; aDetailClassName: TClass; aDetailPropNames: String); //uses for Many-Valued Association
   class procedure RemoveCascadeFlushOnSingleObject(aMappingExplorer: TMappingExplorer; aClassName: TClass; aPropName: String); //Used for Associations
   class procedure AddCascadeFlushOnSingleObject(aMappingExplorer: TMappingExplorer; aClassName: TClass; aPropName: String); //Used for Many-Valued Association
   class procedure AddUniqueIndex(...);//In 3.9: New : DBIndex attribute, i will try it next versio ;)
   ...
   class procedure TDBSchemaTuning.AddCascadeRemoveOrphan(aMappingExplorer: TMappingExplorer; aClassName: TClass; aPropName: String);
   var
     fAssociation: TAssociation;
   begin
     fAssociation := aMappingExplorer.GetAssociationByPropertyName(aClassName, aPropName);
     if fAssociation <> nil then
       fAssociation.Cascade := fAssociation.Cascade + [TCascadeType.RemoveOrphan];
   end;
   ...
   class procedure TDBSchemaTuning.AddCascadeFlushOnSingleObject( aMappingExplorer: TMappingExplorer; aClassName: TClass; aPropName: String);
   var
     fAssociation: TAssociation;
   begin
     fAssociation := aMappingExplorer.GetAssociationByPropertyName(aClassName, aPropName);
     if fAssociation <> nil then
       fAssociation.Cascade := fAssociation.Cascade + [TCascadeType.Flush];
   end;

To add Extra options:
  ...
  AddCascadeRemoveOrphan(TMappingExplorer.Default, TNutPlan, 'FNutPDayList');
  AddCascadeRemoveOrphan(TMappingExplorer.Default, TNutPDay, 'FNutMealList');
  AddCascadeFlushOnSingleObject( TMappingExplorer.Default, TNutPlan, 'NutPDayList');
  AddCascadeFlushOnSingleObject( TMappingExplorer.Default, TNutPDay, 'NutMealList');
  ...
To Save the Object:
  ...  
  Trans := Manager.Connection.BeginTransaction;
  aNewDBObject := Manager.Merge(aNewDBObject);
  Manager.Flush(aNutPMbr);
  Trans.Commit;
  ...

Applying changes:
  when deleting NutMealList item, Flush does not remove orphan.
  when update NutMealList item, Flush does not update item in the database //here i will do more tests to confirm
  when insert NutMealList item, Flush item was inserted in the database

SCHEMA:
...
  [Entity]
  [Table('NutPMbr')]
  [Description('Nutrition Plan Member')]
  [PrimaryJoinColumn('Id')]
  TNutPMbr = class(TNutPlan)
  private
    [Column('NutriotionPlanDate', [TColumnProp.Required])]
    [Description('')]
    FNutriotionPlanDate: TDateTime;
    
    [Column('StartValidity', [TColumnProp.Required])]
    [Description('')]
    FStartValidity: TDateTime;
   
    [Column('EndValidity', [TColumnProp.Required])]
    [Description('')]
    FEndValidity: TDateTime;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('MemberId', [TColumnProp.Required], 'Id')]
    [Description('')]
    FMemberId: Proxy<TMember>;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('NutrioId', [TColumnProp.Required], 'Id')]
    [Description('')]
    FNutrioId: Proxy<TNutrio>;
    function GetMemberId: TMember;
    procedure SetMemberId(const Value: TMember);
    function GetNutrioId: TNutrio;
    procedure SetNutrioId(const Value: TNutrio);
  public
    property NutriotionPlanDate: TDateTime read FNutriotionPlanDate write FNutriotionPlanDate;
    property StartValidity: TDateTime read FStartValidity write FStartValidity;
    property EndValidity: TDateTime read FEndValidity write FEndValidity;
    property MemberId: TMember read GetMemberId write SetMemberId;
    property NutrioId: TNutrio read GetNutrioId write SetNutrioId;
  end;


  [Entity]
  [Table('NutPlan')]
  [Description('Nutrion Food Plan: Plano Alimentar')]
  [Inheritance(TInheritanceStrategy.JoinedTables)]
  [Sequence('Id_NutPlan')]
  [Id('FId', TIdGenerator.IdentityOrSequence)]
  TNutPlan = class
  private
    [Column('Id', [TColumnProp.Required])]
    [Description('')]
    FId: Int64;
   
    [Column('Title', [TColumnProp.Required], 30)]
    [Description('')]
    FTitle: string;
   
    [Column('Comment', [], 120)]
    [Description('')]
    FComment: Nullable<string>;
   
    [Column('RecVersion', [TColumnProp.Required])]
    [Description('')]
    FRecVersion: TDateTime;
   
    [ManyValuedAssociation([TAssociationProp.Lazy, TAssociationProp.Required], [TCascadeType.SaveUpdate, TCascadeType.Merge, TCascadeType.Remove], 'FNutPlanId')]
    FNutPDayList: Proxy<TList<TNutPDay>>;
    function GetNutPDayList: TList<TNutPDay>;
  public
    constructor Create;
    destructor Destroy; override;
    property Id: Int64 read FId write FId;
    property Title: string read FTitle write FTitle;
    property Comment: Nullable<string> read FComment write FComment;
    property RecVersion: TDateTime read FRecVersion write FRecVersion;
    property NutPDayList: TList<TNutPDay> read GetNutPDayList;
  end;


  [Entity]
  [Table('NutPDay')]
  [Description('Nutrition Plan Day')]
  [Sequence('Id_NutPDay')]
  [Id('FId', TIdGenerator.IdentityOrSequence)]
  TNutPDay = class
  private
    [Column('Id', [TColumnProp.Required])]
    [Description('')]
    FId: Int64;
   
    [Column('DayWkId', [TColumnProp.Required])]
    [Description('Day Of Week (enum TDayOfWeekX): dowAllDays(0), dowSunday(1), dowMonday(2),...')]
    FDayWkId: Integer;
   
    [Column('RecVersion', [TColumnProp.Required])]
    [Description('')]
    FRecVersion: TDateTime;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('NutPlanId', [TColumnProp.Required], 'Id')]
    [Description('')]
    FNutPlanId: Proxy<TNutPlan>;
   
    [ManyValuedAssociation([TAssociationProp.Lazy, TAssociationProp.Required], [TCascadeType.SaveUpdate, TCascadeType.Merge, TCascadeType.Remove], 'FNutPDayId')]
    FNutMealList: Proxy<TList<TNutMeal>>;
    function GetNutPlanId: TNutPlan;
    procedure SetNutPlanId(const Value: TNutPlan);
    function GetNutMealList: TList<TNutMeal>;
  public
    constructor Create;
    destructor Destroy; override;
    property Id: Int64 read FId write FId;
    property DayWkId: Integer read FDayWkId write FDayWkId;
    property RecVersion: TDateTime read FRecVersion write FRecVersion;
    property NutPlanId: TNutPlan read GetNutPlanId write SetNutPlanId;
    property NutMealList: TList<TNutMeal> read GetNutMealList;
  end;


  [Entity]
  [Table('NutMeal')]
  [Description('')]
  [Sequence('Id_NutMeal')]
  [Id('FId', TIdGenerator.IdentityOrSequence)]
  TNutMeal = class
  private
    [Column('Id', [TColumnProp.Required])]
    [Description('')]
    FId: Int64;
   
    [Column('MealTime', [TColumnProp.Required])]
    [Description('MealTime: Hora da Refeição')]
    FMealTime: TDateTime;
   
    [Column('FoodDescription', [], 256)]
    [Description('')]
    FFoodDescription: Nullable<string>;
   
    [Column('RecVersion', [TColumnProp.Required])]
    [Description('')]
    FRecVersion: TDateTime;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('NutPDayId', [TColumnProp.Required], 'Id')]
    [Description('')]
    FNutPDayId: Proxy<TNutPDay>;
   
    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('NutMTypId', [TColumnProp.Required], 'Id')]
    [Description('')]
    FNutMTypId: Proxy<TNutMTyp>;
    function GetNutPDayId: TNutPDay;
    procedure SetNutPDayId(const Value: TNutPDay);
    function GetNutMTypId: TNutMTyp;
    procedure SetNutMTypId(const Value: TNutMTyp);
  public
    property Id: Int64 read FId write FId;
    property MealTime: TDateTime read FMealTime write FMealTime;
    property FoodDescription: Nullable<string> read FFoodDescription write FFoodDescription;
    property RecVersion: TDateTime read FRecVersion write FRecVersion;
    property NutPDayId: TNutPDay read GetNutPDayId write SetNutPDayId;
    property NutMTypId: TNutMTyp read GetNutMTypId write SetNutMTypId;
  end;
...


T H A N K S S S S S S :)

Thank you very much for detailed information. Unfortunately I still cannot spot what could be causing the issue you are getting. 


When you simply call Flush for the whole manager, does it work?
What if, just for testing, you manually add the cascades to the associations directly in the mapping, without calling your code that adds it at runtime? Does it work?

Hi
  If i call  Manager.Flush(), instead of Manager.Flush(aNutPMbr), it's OK.
  The issue is Fushing single Object.
  I will try what you suggest

Thanks

sorry, my mistake
  Everything works as expected. Wrong parameters when call "AddCascadeFlushOnSingleObject"
and "AddCascadeRemoveOrphan"

To add Extra options(correct version):
  ...
  AddCascadeRemoveOrphan(TMappingExplorer.Default, TNutPMbr, 'FNutPDayList');
  AddCascadeRemoveOrphan(TMappingExplorer.Default, TNutPDay, 'FNutMealList');
  AddCascadeFlushOnSingleObject( TMappingExplorer.Default, TNutPMbr, 'NutPDayList');
  AddCascadeFlushOnSingleObject( TMappingExplorer.Default, TNutPDay, 'NutMealList');

Thanks, sorry again