We're currently evaluating Aurelius to know if it would fit our needs and it's doing pretty good so far.
We only struggle on one point :
We have a property form which displays a list of items. There can be as many items in the list as the configuration needs. So we would be declaring a "TItem" with a [Entity] tag, that's all fine.
But we need to let the user modify this list (add/update/delete items) and finally cancel his changes if he's not satisfied.
How would you recommend us to do so?
We've thought about 3 ways for now:
Use a TAureliusDataset, load it and make the changes on this dataset and then "Apply" the dataset or "discard" it. Pros : That should work and we can load the dataset with the Aurelius ObjectManager apparently. Which is good Cons : that's way less convenient than working with objects, and that's the whole point of an ORM right?
Only let the user change the graphic items and then perform a "manual sync" between the GUI items and the content of the DB... hum Pros : none Cons : Risk of bugs, not evolutive etc...
Use a transaction, save the TItem as the user modify them and commit the transaction if he applies his change. Rollback otherwise. Pros : pretty straightforward and easy Cons : We would have to deal with DB concurency, locks etc.. We're a cross DBMS app so that would be difficult to handle on 4 different DBMS (to be honnest that's why we want an ORM too, do the non DBMS-agnostic job for us)
Anything else comes to your mind?
Are we completely mis-understanding something? How does other people in the community implements such mechanisms?
I don't understand if your problem is mainly on the user interface, or object manipulation? Also using a transaction is not mutually exclusive with the other options. For user interface, the dataset is the best option because it does the binding with controls automatically. It has nothing to do with "not working with objects" because it's only for the binding (that's a misunderstanding most people do). The objects are still behind the dataset.
But for saving the objects in the database, if you need to save all-or-nothing, including inserts, updates, etc., then you must use the transaction, I don't see why it would not be agnostic? Why need locks? I think I'm a little confused with your exact needs.
Alright so you would recommend working with TAureliusDataset and Apply it afterwards.
That's fine to me for the cases where we'll be working with DBAware GUI components, it makes it dead simple.
But what if we don't want/can to work with such components right now? We would have to implement the "synchronisation" mechanism between the control and the dataset ourselves right? -> writing in the dataset through .FieldByName('name') := val
>>>Alright so you would recommend working with TAureliusDataset and Apply it afterwards.
Only for GUI binding, not for operations. I said I didn't understand well what you need.
If you want to present data in a Delphi form and don't want to use Aurelius Datatset, then you have to manually read data from objects and set in your visual controls. Or use live bindings.
If you use SetSourceList to provide the list used by the aurelius dataset, it will automatically add/remove items from that list when you Insert/Delete records to/from dataset.
Have you checked the new Refresh method? It allows you to rollback the object to its original state, thus changes made to that object will be discarded.
But I don't see how extracting an object from the manager would help in this case?
This is the same case of the regular TDataset. If you delete a record, it's gone. You must either:
1. Do not delete/remove the object until the user confirm the changes. If you want to rollback things, why are you effectively removing it?
2. Use transactions and then rollback if user cancels it. After the rollback you need to perform the query again, as you would do with a TDataset.Refresh.