Saving child classes

Hello!

I have a master class and some one-to-many sub classes.

Here's the code:

    if Doc.DocId<1 then begin
      Doc.DocId := Self.GetDocMax(Doc.BusinessYear.ToInteger, doc.DocType.Value.Id)+1;
    end;

    FManager.Merge(Doc);
    FManager.Flush(Doc);

Here are the classes (simplified):

  [Entity]
  [Table('doc_headers')]
  [Id('FId', TIdGenerator.IdentityOrSequence)]
  [UniqueKey('BUSINESS_YEAR,DOC_TYPE,DOC_ID')]
  TDocument = class(TBaseObject)
  private
    [Column('ID')]
    FId: integer;

    [Column('BUSINESS_YEAR')]
    FBusinessYear: string;

    [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('DOC_TYPE', [])]
    FDocType: Proxy<TDocType>;

    [Column('DOC_ID')]
    FDocId: integer;
    ...

    [Transient]
    FSpecification: Proxy<TList<TDocItem>>;
    [Transient]
    FParamList: Proxy<TList<TDocParam>>;
  public
    [ManyValuedAssociation([TAssociationProp.Lazy], CascadeTypeAllRemoveOrphan, 'FHeaderId')]
    property Specification: Proxy<TList<TDocItem>> read FSpecification write FSpecification;

    [ManyValuedAssociation([TAssociationProp.Lazy], CascadeTypeAllRemoveOrphan, 'FHeaderId')]
    property Params: Proxy<TList<TDocParam>> read FParamList write FParamList;
  end;

  [Entity]
  [Table('doc_items')]
  [Id('FIndex', TIdGenerator.IdentityOrSequence)]
  [Id('FHeaderId', TIdGenerator.None)]
  TDocItem = class(TBaseObject)
  private
    [Column('IDX')]
    FIndex: integer;

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

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

    [Column('DESCRIPTION')]
    FDescription: string;
    ...

  public
    property Idx: integer read FIndex write FIndex;
    property Document: Proxy<TDocument> read FHeaderId write FHeaderId;
    property Product: Proxy<TStockItem> read FProduct write FProduct;

    property Description: string read FDescription write FDescription;
    ...
  end;

  [Entity]
  [Table('doc_params')]
  [Id('FHeaderId', TIdGenerator.IdentityOrSequence)]
  [Id('FParName', TIdGenerator.None)]
  TDocParam = class(TBaseObject)
  private
    [Association([TAssociationProp.Lazy], [])]
    [JoinColumn('HEADER_ID', [])]
    FHeaderId: Proxy<TDocument>;

    [Column('PARAM')]
    FParName: string;

    [Column('IDX')]
    FIndex: integer;

    [Column('VALUE')]
    FParValue: string;

    [Column('EXTRA')]
    FExtra: string;

    [Column('IS_VISIBLE')]
    FVisible: boolean;
  public
    property Document: Proxy<TDocument> read FHeaderId write FHeaderId;
    property ParName: string  read FParName write FParName;
    property ParValue: string  read FParValue write FParValue;
    property Idx: integer read FIndex write FIndex;
    property Extra: string read FExtra write FExtra;
    property Visible: boolean  read FVisible write FVisible;

    constructor Create(Name, Value, ParExtra: string; IsVisible: boolean; Index: integer); overload;
  end;

My problem is that the class TDocument is saved, but the classesi nFpecification and FParams are not. I checked the documentation but I'm unable to fix the problem. Pretty sure that I'm doing something wrong, but can't figure out what.

Posted too quick - Here's the code (simplified):

    .. the document is created and populated ..
    Doc := TDocument.Create;

    DocItem := TDocItem.Create;
    DocItem.Document.Value := Doc;
    Doc.Specification.Value.Add(DocItem);

    FManager.Merge(Doc);
    FManager.Flush(Doc);

Hi @GOMEZEL_DINO, your code can improve in some parts. First, composite ids cannot have identity/sequence generators. They have to be none:

  [Id('FIndex', TIdGenerator.None)]
  [Id('FHeaderId', TIdGenerator.None)]
  [Id('FHeaderId', TIdGenerator.None)]
  [Id('FParName', TIdGenerator.None)]

Second, keep in mind that Merge always return a new instance from manager (unless the instance is already there). Thus, the correct code is this:

MergedDoc := FManager.Merge(Doc);
FManager.Flush(MergedDoc);

or simply:

  FManager.Flush(Manager.Merge(Doc));

Third, your FHeaderId association is missing cascades. Not sure if this intentional, if not, then this is the recommended:

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

Fourth, why are you mapping public proxied properties instead of the private fields. There is no problem with that, but then you defeat the purpose of the proxies, having to deal with the Proxy type directly from the public properties.

In any case, I believe the cause of your issue is problem #2.

thank you - also for the extra tips! I will check and report here for documentation purposes.

1 Like

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