What am i doing wrong?


I've declared these two classes (via Data Modeller):

  [Id('FUserTSID', TIdGenerator.IdentityOrSequence)]
  TUserTS = class
    [Column('UserTSID', [TColumnProp.Required, TColumnProp.NoInsert, TColumnProp.NoUpdate])]
    FUserTSID: integer;

    [Column('CreateUser', [])]
    FCreateUser: Nullable<integer>;

    [Column('CreateTS', [], 65536)]
    FCreateTS: Nullable<string>;

    [Column('ModifyUser', [])]
    FModifyUser: Nullable<integer>;

    [Column('ModifyTS', [], 65536)]
    FModifyTS: Nullable<string>;

    [Column('Comments', [], 65536)]
    FComments: Nullable<string>;
    property UserTSID: integer read FUserTSID write FUserTSID;
    property CreateUser: Nullable<integer> read FCreateUser write FCreateUser;
    property CreateTS: Nullable<string> read FCreateTS write FCreateTS;
    property ModifyUser: Nullable<integer> read FModifyUser write FModifyUser;
    property ModifyTS: Nullable<string> read FModifyTS write FModifyTS;
    property Comments: Nullable<string> read FComments write FComments;

  [Id('FSysPrefsID', TIdGenerator.IdentityOrSequence)]
  TSysPreferences = class
    [Column('SysPrefsID', [TColumnProp.Required, TColumnProp.NoInsert, TColumnProp.NoUpdate])]
    FSysPrefsID: integer;

    [Column('LastUser', [])]
    FLastUser: Nullable<integer>;

    [Column('MultiUser', [])]
    FMultiUser: Nullable<integer>;

    [Association([TAssociationProp.Lazy], [])]
    [JoinColumn('UserTSID', [], 'UserTSID')]
    FUserTSID: Proxy<TUserTS>;
    function GetUserTSID: TUserTS;
    procedure SetUserTSID(const Value: TUserTS);
    property SysPrefsID: integer read FSysPrefsID write FSysPrefsID;
    property LastUser: Nullable<integer> read FLastUser write FLastUser;
    property MultiUser: Nullable<integer> read FMultiUser write FMultiUser;
    property UserTSID: TUserTS read GetUserTSID write SetUserTSID;

Then, in code I try to create a record like this:

    AppDatabases.GetObjectManager.Save(tmpSys); //This returns a reference to ObjectManager

and compiler (Delphi XE7) complains that "Association references a transient object"

I've checked the manual and know the difference between transient/persistent objects. When I check the class declarations I think both TUserTS and TSysPreferences are persistent.

So, what am I doing wrong here?



You create both objects outside of an object manager - they're both transient at that point. You then save tmpSys, which makes it managed, but tmpTS is still transient - it hasn't been saved or loaded via the object manager.

Now I understand. So, I have to first save tmpTS before I save tmpSys, right?

Thanks for the tip

Yes , that should fix your problem.

Or you can include TCascade.SaveUpdate in association cascades so it's saved automatically when the parent object is save:

    [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('UserTSID', [], 'UserTSID')]
    FUserTSID: Proxy<TUserTS>;

Hi Wagner,

thanks for this. Is there a way I can make Data Modeler to generate this statement automatically?



Yes, you have an option named "Association Cascade Type" that you can choose that option as default for all associations. Or you can specify it for each association.

Thanks for this.

Two questions here:

1) Based on my code above, what does it mean? If SysParam record is removed then the UserTS is not removed, right? or the other way around?

2) Why isn't there an option as default to CascadeAll? Instead of ButRemove?


  1. Yes, when TSysPreference object is saved, updated, refreshed, merged, etc., the same operation will be performed (before) in UserTS. Except removing.

    2) There is, it's just the usually it's more common that you don't remove (or try to remove) an associated object, because in theory it could be associated to other objects. Your UserTS object might be associated with more than one SysParameter object, so trying to remove it as well might cause an error. It's a analog situation to Invoice/customer. When you delete an invoice, you don't want to delete the customer that was associated with the invoice.

    But if fits your model, yes, you just use CascadeTypeAll

Hi Wagner,

thanks for the reply. it makes sense to me what you write. 

In this particular case, the CascadeTypeAll fits in my design so I will go with this.

It would be very helpful to add this option in the Aurelius export dialog as I now have a big number of tables and I need to update the unit manually (in order to remove the - [cascaderemove] tag)


Ok, a new TMS Data Modeler update is available with that improvement..

That's great. 

Thanks for the quick response.