Hi,
In my project I have two tables:
Store (ID, StoreNum, Name, Location)
Item (ID, StoreID, Name, Price)
Store has a unique constraint on StoreNum column.
The Item's StoreID column references the Store table's ID (foreign key).
I use the following nhibernate mapping:
Item
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="SandlinksReaderDSPI.Model"
assembly="SandlinksModel">
<!-- Mappings for class 'Customer' -->
<class name="Item" table="items" lazy="false">
<!-- Identity mapping -->
<id name="ID">
<column name="ID" />
<generator class="native" />
</id>
<column name="Name"/>
<column name="Price"/>
<many-to-one name="Store" column="StoreID" ass="Store" not-null="true" />
</class>
</hibernate-mapping>
================
Store
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="SandlinksReaderDSPI.Model"
assembly="SandlinksModel">
<!-- Mappings for class 'Customer' -->
<class name="Store" table="observation" lazy="false">
<!-- Identity mapping -->
<id name="ID">
<column name="ID" />
<generator class="native" />
</id>
<!-- Simple mappings -->
<property name="StoreNum" />
<property name="Name" />
<property name="Location" />
<bag name="Items" table="items"
inverse="true" cascade="all-delete-orphan">
<key column="StoreID" />
<one-to-many class="Item" />
</bag>
</class>
</hibernate-mapping>
=============================================
When I try to save a
new store object that already has items in its list, everything workes great. The store is added and so are its items.
Loading, Updating and deleting a store / item works great as well.
But... This only works if the store doesn't exist in the DB already.
My project gets a text file of stores and itesm each day. Its goal is to iterate it, create store object, fill it with it's items and save it to the db.
A situation where the store I'm currently trying to save already exists in the DB (same StoreNum) is very common.
When I try to do
Code:
seesion.save(store)
, I get a justified exception:
Quote:
Violation of UNIQUE KEY constraint 'U_Store_StoreNum'. Cannot insert duplicate key in object 'dbo.store'. The statement has been terminated.
Since I'm not running in a transaction, In that case i'd like to continue to the next store and silently discard the error.
The problem is that when I finally do
Code:
session.Flush()
I get this nasty exception:
NHibernate.PropertyValueException: not-null property references a null or transient value: MyModel.Item.Store
at NHibernate.Impl.SessionImpl.CheckNullability(Object[] values, IEntityPersister persister, Boolean isUpdate)
at NHibernate.Impl.SessionImpl.DoSave(Object theObj, EntityKey key, IEntityPersister persister, Boolean replicate, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.DoSave(Object obj, Object id, IEntityPersister persister, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
at NHibernate.Engine.Cascades.CascadingAction.ActionSaveUpdateClass.Cascade(ISessionImplementor session, Object child, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.CascadeCollection(CascadingAction action, CascadeStyle style, CollectionType collectionType, IType elemType, Object child, CascadePoint cascadeVia, ISessionImplementor session, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, Object child, IType type, CascadingAction action, CascadeStyle style, CascadePoint cascadeTo, Object anything)
at NHibernate.Engine.Cascades.Cascade(ISessionImplementor session, IEntityPersister persister, Object parent, CascadingAction action, CascadePoint cascadeTo, Object anything)
at NHibernate.Impl.SessionImpl.PreFlushEntities()
at NHibernate.Impl.SessionImpl.FlushEverything()
at NHibernate.Impl.SessionImpl.Flush()
at MyDAL.MyDao.Flush()
It looks like Nhibernate tries to save the Item/s even though it failed earlier while trying to save the parent store.
I believed that in case NH fails to persist the parent object, it won't try to save the child elements - it makes no sense!
I know I can try to load a store with a given StoreNum and delete it if it exists, but this requiers executing 2 unnecessary sql statements (select & delete) for each store!
when a table is realy big it'll take too much time even when indexed.
Can someone review this and tell me if I'm doing something wrong?
Can I specifically tell NH to ignore chiled elements in this case, maybe by mapping differently?
Thanks,
Shaul