Refresh(parentObject) would be a good option, but for me, it first fetched all children one by one with single requests. No batching, no subquery, no join. Very bad!
It helped to .Clear() the child collection of the parent object; I also evicted the child objects before.
(these had been changed by a HQL update before where multiple inserts by parent/children SaveOrUpdate would cause expensive clustered index rebuilds).
EDIT: I removed the HQL update again, since the query (decrement index by a unique, large number) was more expensive than hundreds of single row updates in a batch. So I ended up in a simple SaveOrUpdate(parentObject), with no need to refresh.
The reason was a child collection with unique constraint on ParentID and Index (sequential number), which would result in uniqueness violations while updating the changed children items. So the index was first incremented by 1000000 (or an arbitrary high number) for all children, then after changes, decremented again.