I am using the Repo pattern, and I have set up tests to replicate my a HTTP request coming in and then causing dispose on a unit of work once a test has completed.
It appears that after executing a HQL statement, and then calling displose (which in turn calls flush) that it is causing an update across various elements.
Very bizzare - has anyone come across this before?
Here is my HQL statement and it's execution:
_session.CreateQuery("select distinct t from TaskEntity as t").List<T>()
I've pulled this back to it's simplest form - and note the HQL statement is not directly in the CreateQuery.
Here is the stack trace I am getting:
I
BM.Data.Informix.IfxParameterCollection.b(Int32 A_0)
IBM.Data.Informix.IfxParameterCollection.GetParameter(Int32 index)
System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item(Int32 index)
NHibernate.Type.Int32Type.Set(IDbCommand rs, Object value, Int32 index)
NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd, Object value, Int32 index)
NHibernate.Type.NullableType.NullSafeSet(IDbCommand st, Object value, Int32 index, ISessionImplementor session)
NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColumns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index)
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
NHibernate.Action.EntityUpdateAction.Execute()
NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
NHibernate.Engine.ActionQueue.ExecuteActions()
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
NHibernate.Impl.SessionImpl.Flush()
Case.Data.SQL.NHibernateUnitOfWork.Dispose() in C:\Projects\Case System\Dev\WorkingBranch\Src\Case.Data.SQL\NHibernateUnitOfWork.cs: line 46
Case.Domain.Tests.TaskServicesTests.TakeDown() in C:\Projects\Case System\Dev\WorkingBranch\Src\Case.Domain.Tests\TaskServicesTests.cs: line 40
I faced a similar problem. I'll first tell you what causes this. When NHibernate
fetches an entity from the DB
it assigns values to it's props. There are few props that have null values in the DB
but are not of Nullable
type in the class definition. So NHibernate
assigns them a default value eg. 0
for int
, DateTime.MinValue
for datetime
etc. When you call commit on the transaction, NHibernate
rechecks the values of properties with DB
values and since props which should have had Null
values now have a default value, NHibernate
thinks that the values have been changed and causes an update.
Solution:
nullable datatypes
for your class props by post fixing them with
?
but for me this is causing other problems.Not Null
Types but this is not preferable in
most cases.Null
values
in the Db
Nhibernate
saves some default value and this stops the
calls to unnecessary updates.You may further google NHibernate ghostbuster
for more research on this problem.