NHibernate: SaveOrUpdate - Duplicate Key Exception on Child - nhibernate

I have a web application I've developed that has a fairly complex save routine. The user builds and modifies a series of plans and then chooses to save the data. All of the additions, deletions, and modifications are saved in one go at this point (all inside a single transaction).
Plan
Collection Of Child
Collection of ChildDetail
The bulk of the save is performed by calling SaveOrUpdate on a plan object and letting this save manage the plan and it's children. I use zero as the unsaved value when I want to insert a new record and use cascade=all-delete-orphan to ensure that if a child object or child detail object is removed on the client side the object is deleted.
I am receiving an exception however when the following happens: A user creates a plan with child objects and saves them. This will save fine.
Plan(id=0)
Child[0](id=0), Child[1](id=0), Child[2](id=0)
If the user then removes the child objects, and adds new child objects in their place and then attempts to save the changes.
Plan(id=123)
Child[0](id=0), Child[1](id=0), Child[2](id=0)
This throws a GenericAdoException unable to insert Child with an inner exception "SQL0803 Duplicate Key Value Specified".
The behavior I'm looking for is for NHibernate to delete the previous Child objects then insert the new ones when SaveOrUpdate is called on the Plan. How can I achieve this while still letting the parent manage the relationships?

A solution I found for the time being is to pass the Ids of the removed children to the save routine. I then set the ids of the new children to the ids of the removed children. Effectively turning a remove/add into an update.

Related

How does SQLAlchemy load related objects from the local identity map for a simple many-to-one relationship?

According to the SQLAlchemy docs:
The one case where SQL is not emitted is for a simple many-to-one
relationship, when the related object can be identified by its primary
key alone and that object is already present in the current Session.
For this reason, while lazy loading can be expensive for related
collections, in the case that one is loading lots of objects with
simple many-to-ones against a relatively small set of possible target
objects, lazy loading may be able to refer to these objects locally
without emitting as many SELECT statements as there are parent
objects.
Assume that:
A Parent can have many Child, while a Child has only one Parent.
Parent has a relationship children = relationship('Child', back_populates='parent', lazy='select')
parent_0 is an instance of Parent and child_0, child_1 are instances of Child, whose parent is parent_0.
If I've understood it correctly, this means the first time I access parent.children, SQLAlchemy would check the local identity map for related objects (i.e. Child instances referencing parent_0), and would query the database if nothing is found.
My question is, how does it know which Child instances are related to parent_0 without querying the database? Even if all Child instances have been loaded to the local identity map, this only means "all Child instances can be accessed through their primary keys without having to query the database", or alternatively "given a specific primary key, it can return a Child instance without having to query the database". The problem is, without querying the database,how does SQLAlchemy know what the primary keys of the related objects of parent_0 are?
If it don't know, then I can't understand how loaded Child instances can help to bypass the database query.

Nhibernate bag collection when is it re-creating?

I made a lot of examples to check when bag collection is recreating during adding or removing item from collection. I read that in http://knol.google.com/k/nhibernate-chapter-16-improving-performance section 16.5.1. Taxonomy:
Bags are the worst case. Since a bag
permits duplicate element values and
has no index column, no primary key
may be defined. NHibernate has no way
of distinguishing between duplicate
rows. NHibernate resolves this problem
by completely removing (in a single
DELETE) and recreating the collection
whenever it changes. This might be
very inefficient.
I made bidirectional of type one to many(Person -> Addresses) and the following tests:
Test 1: Inverse= false; action=insert,update,remove,count; Collection types: Set, Bag
Result: Collections behave exactly the same!
Test 2: Inverse= true; action=insert,update,remove,count; Collection types: Set, Bag
Result: Collections behave almost the same! I only see difference in adding new item to bag collection - when i do that collection is not filled with data from db.
I was using nhibernate profiler/session statystics for analizying changes in session object and in database. But i did not see any recreating items of collection, whed did it happend? i memory?
Recreating collections applies only for entities loaded from the database. When running tests in the same session that the entities were created, NHibernate knows that the collections are empty, manipulates it in memory and saves only the final state to the database on transaction commit/session flush.
I've done similiar tests - see this blog entry for example of re-creating bag collection.

Does core data delete objects with cascading delete rules instantly or on-save?

In a Core Data model, entity A has a relation to entity B with the delete rule set to Cascade. Is object B immediately deleted when the [context deleteObject:A] is called, or does Core Data wait for the [context save:&error] method, like it does with object validation?
I'm wondering if after deleting A, I could create an object C that would then search for B in the context and establish the relation. Would that prevent B from being deleted?
Cheers,
Eric-Paul.
"Deleted" is merely a state. How that state is persisted when the user (or your app) saves is an implementation detail. It can still be undone after a save if the file hasn't been closed and its state lost.
If your intention is to move the B instances of an A instance to another instance of A, you need to change the relationship before you delete the first A instance, else the cascade rule will take the Bs with it (per the exact definition of the rule's behavior). Once deleted (whether directly or by a cascade rule), it's deleted. Searches won't reveal deleted Bs.
So: if you want to preserve an A's Bs, assign the Bs to another A before deleting the original. Otherwise, you'll need to create new Bs for the new A.

What's the best way to refresh entities in nhibernate

I would like to refresh an entity and all its child collections. What is the best way to do this? I'm talking about nhibernate:)
I've read about session.Evict, session.Refresh...
But I'm still not sure if doing like:
RefreshEntity<T>(T entity)
{
session.Evict(entity);
session.Refresh(entity);
}
would work exactly how I want it to work
Is it going to work? If not What else I can do?
Refresh after Evict probably won't work.
Theoretically, Refresh alone should be enough. However, it has known issues when elements of child collections have been deleted.
Evict followed by Get usually gets things done.
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.

Using nHibernate, how can I get the newly inserted ID during an Add?

When I am adding a new row in the database, I noticed the Add method returns void.
Is it possible to get the newly created row's ID returned in the add operation?
When you call session.Save() on your entity, your entity should have the Id modified.
You probably want to check your nhibernate configuration if your save is occurring immediately or if your saving is batching. If it's batching, then you'll need to commit (or flush, someone will correct this... hopefully) your session.