Something wrong with ObjManager.Refresh

Hello.


I have a project with Aurelius 2.6. When in modal form user press "Cancel", I refresh object with ObjManager.Refresh, because some data in object may be changed in form. It's work when I use simple object, but when I try to use mapped object with ManyValuedAssociation - I got an exception when try to access ManeValue-list.

I create a test project, which repeats error.

At first, create a test tables (Oracle syntax):


create table test_test.master
(
  id    number,
  title varchar2(100 char)
)
;
alter table test_test.master
  add constraint pk_master primary key (ID);


create table test_test.detail
(
  id        number,
  master_id number not null,
  val       number
)
;
alter table test_test.detail
  add constraint pk_detail primary key (ID);
alter table test_test.detail
  add constraint fk_detail_master foreign key (MASTER_ID)
  references test_test.master (ID);
Two simple tables, master and detail. Insert in master one row with ID = 1. Detail is empty (or not, it does not matter).

For Delphi-mapping I use Data Modeler db reverse (with some property renames):

  TDetail = class;
  TMaster = class;


  [Entity]
  [Table('DETAIL')]
  [Id('FID', TIdGenerator.None)]
  TDetail = class
  private
    [Column('ID', [TColumnProp.Required])]
    FID: double;


    [Column('VAL', [])]
    FValue: Nullable<double>;


    [Association([TAssociationProp.Lazy, TAssociationProp.Required], CascadeTypeAll - [TCascadeType.Remove])]
    [JoinColumn('MASTER_ID', [TColumnProp.Required], 'ID')]
    FMaster: Proxy<TMaster>;


    function GetMaster: TMaster;
    procedure SetMaster(const Value: TMaster);
  public
    property ID: double read FID write FID;
    property Value: Nullable<double> read FValue write FValue;
    property Master: TMaster read GetMaster write SetMaster;
  end;


  [Entity]
  [Table('MASTER')]
  [Id('FID', TIdGenerator.None)]
  TMaster = class
  private
    [Column('ID', [TColumnProp.Required])]
    FID: double;


    [Column('TITLE', [], 400)]
    FTitle: string;


    [ManyValuedAssociation([TAssociationProp.Lazy, TAssociationProp.Required], [TCascadeType.SaveUpdate, TCascadeType.Merge], 'FMaster')]
    FDetails: Proxy<TList<TDetail>>;


    function GetDetails: TList<TDetail>;
  public
    constructor Create;
    destructor Destroy; override;
    property ID: double read FID write FID;
    property Title: string read FTitle write FTitle;
    property Details: TList<TDetail> read GetDetails;
  end;




implementation


{ TDetail}


function TDetail.GetMaster: TMaster;
begin
  result := FMaster.Value;
end;


procedure TDetail.SetMaster(const Value: TMaster);
begin
  FMaster.Value := Value;
end;


{ TMaster}


constructor TMaster.Create;
begin
  FDetails.SetInitialValue(TList<TDetail>.Create);
end;


destructor TMaster.Destroy;
begin
  FDetails.DestroyValue;
  inherited;
end;


function TMaster.GetDetails: TList<TDetail>;
begin
  result := FDetails.Value;
end;


And then I use this code:

procedure TForm1.ButtonClick(Sender: TObject);
var
  M: TMaster;
begin
  M  :=  Manager.Find<TMaster>(1);


  M.Title :=  'new title; detail count = ' + IntToStr(M.Details.Count);


  Manager.Refresh(M);


  ShowMessage(IntToStr(M.Details.Count));
end;


When I try to call M.Details.Count second time, I got an exception:

What I do wrong? Is there an error in mapping code?

Now I use small trick to do refresh, but without refresh:


var
  M: TMaster;
  vID: Double;
begin
  M  :=  Manager.Find<TMaster>(1);


  M.Title :=  'new title; detail count = ' + IntToStr(M.Details.Count);


  vID :=  m.ID;
  Manager.Evict(M);
  M.Free;
  M :=  Manager.Find<TMaster>(vID);


  ShowMessage(IntToStr(M.Details.Count));

It's work, but it's not good decission - in app may be another links to this object...

It seems to be a bug we have already fixed but didn't release yet. Can you please send us a private e-mail so I can send you the patch to see if the problem is gone.

Submit message via private form.