Duplicating a TEntity

Given a structure like TOrder->TPosition - what would be the best way to implement a "new with this data" feature?



I used to work with client datasets and had a generic way to do create a new master record along with child records and seek a way to do the same with Aurelius.



Maybe it is easiest at the TAureliusDataset-level?



tx for every idea!

Hi Bernd, sorry but I didn't understand your question. Are you talking about saving the whole structure at once? If that's the case, then you just need to create TOrder instance, a bunch of TPosition instances, add them to a TOrder.Positions property that is a TList<TPosition> and then save TOrder, the parent and all children will be saved at once.

No, saving is not the point.

What I want is a generic solution for "take this record and its children and grandchildren ..." and create a new record, containing the same data. 

Kind of "duplicate this record":
NewOrder:=OldOrder.Duplicate;



One option is to clear the ID of the object and Merge it into another manager:



Obj := Manager.Find<TMyClass>(1);
Manager2 := TObjectManager.Create(Conn);
Obj.Id := 0;
Manager2.Merge<TMyClass>(Obj);


Note that this is the most simple one. If you have lots of associated objects it's up to you to iterate through the three and clear the ID of those objects you want to save a new copy (create a new id) or keep the id of the associated objects if you want both main objects to reference the same associated one.

Ok, thanks for this.


But given this:

TInvoice = class
private

  FCustomer: TCustomer;

  FInvoiceItems: TList<TInvoiceItem>;


What happens to the FInvoiceItems then? 


In most operations that TObjectManager performs, the operations are cascaded to associated objects if such operation is flagged to be cascaded (See CascadeType: http://www.tmssoftware.biz/business/aurelius/doc/web/association.html)

Thus, in the above example, if you Merge TInvoice and the FInvoiceItems association is flagged with TCascadeType.Merge, they will be merged as well.

This is quite cool, but:
According to the doc: "The only exception is the one described above when the object has no id, or when Replicate saves a new object with existing id. In those cases, a Save (insert) operation is performed immediately in the database." 

This means, that calling merge on an Entity with no id (as above in your example) writes the data to the database. This is not what I want, because the user eventually cancels his Edits.

You just want to clone the object. In this case it's out of Aurelius scope and you could simply clone it manually or using RTTI. Aurelius has an internal method to do that which can be called using



TMappingExplorer.Default.CopyFieldValues(Source, Target);


But note that this method doesn't clone any of the associated objects (be it single association or objects in lists). In this case you would still need to interact through associations and clone them as well.