kacha07 wrote:
I rather the order of saving always follows the hierarchy of the relationships. I mean, first the master entity and after the child entities, no matter what is the IsNew flag value.
It is possible to force this behavior?
The way LLBLGen construct the actions to take and the order the should be executed is complex and perfect. It takes into account a lot of information on your graph to know what has to be saved first, and what later.
At a great scale when you save a collection this is what happens:
1. Determine the insert actions
2. Determine the update actions
3. Determine the delete actions
The order of those actions are (normally): 1,2,3. You can customize this is you want using UnitOfWorks.
Now, for each (1) and (2), and for each involved entity inside those entities, the dependencies are checked to know what depends on what, this is done by LLBLGen's ObjectGraphUtils.ProduceTopologyOrderedList, so it produces a list of entities in the root entity graph ordered by their dependencies. Then each entity in this ordered list is evaluated to know what to do with it, it may be that it should be inserted, or updated, or it's FK field needs to be updated, etc. For instance, if you are saving an Order and it's Customer, these are the options:
a. If the Order is new, and the Customer is new as well, then you must save first the Customer, then the Order, otherwise you will get an FK violation.
b. If the Order is not new and the Customer is new, then is the same case (a).
c. If the Order is new and the Customer is not, then you only need to update the customer (if it has been changed) and insert the Order. In this case the order is saved first, as that is the normal ordering (explained earlier in this post).
d. If the Order is not new and the Customer is not new as well, then you just need to update both, the order is updated first, as it was added first to the update queue.
So, to clarify: the behavior you are seeing is not about parent and child, it's about what to do first (insert, updates or deletes). The default behavior is to do inserts first, no matter if they are AEntity, BEntity or CEntity, then updates, then deletes.
If you want to do updates first you need to use a UnitOfWork. Example:
// suppose you have some 'myA' entity (AEntity) that has Bs childs (BEntity), and each B
// has a Cs collection (CEntity)
// ...
// create a unit of work with custom action ordering
var customSaveOrdering = new List<UnitOfWorkBlockType>();
customSaveOrdering.Add(UnitOfWorkBlockType.Updates);
customSaveOrdering.Add(UnitOfWorkBlockType.UpdatesPerformedDirectly);
customSaveOrdering.Add(UnitOfWorkBlockType.Inserts);
customSaveOrdering.Add(UnitOfWorkBlockType.Deletes);
customSaveOrdering.Add(UnitOfWorkBlockType.DeletesPerformedDirectly);
var uow = new UnitOfWork2(customSaveOrdering);
/// add the root entity graph to save, recursively,
/// so all related objects to this order are
uow.AddForSave(myA, null, false, true);
// save
using (var adapter = new DataAccessAdapter())
{
uow.Commit(adapter);
}