2012-04-12 2 views
1

Я использую шаблон Repo, и я настроил тесты для репликации моего HTTP-запроса, входящего в систему, а затем выставив его на единицу работы после завершения теста.Nhibernate Flush вызывает обновления там, где их не должно быть

Похоже, что после выполнения инструкции HQL и вызова вызова (который, в свою очередь, вызывает сброс), он вызывает обновление для разных элементов.

Very bizzare - есть ли у кого-нибудь знакомые?

Вот мое HQL заявление, и это исполнение:

_session.CreateQuery("select distinct t from TaskEntity as t").List<T>() 

Я вытащил это обратно к его простейшей форме - и обратите внимание на заявление HQL не непосредственно в CreateQuery.

Вот трассировки стека я получаю:

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 
+0

Могу ли я спросить, как вы заметили, что происходит ленивая загрузка? – Rippo

+0

Я смотрел его через профилировщик NHibernate - проблема, кажется, исчезла и теперь заменяется операциями обновления, которые пытаются называться - у меня просто выполняется инструкция HQL - я отредактирую свой вопрос, чтобы он соответствовал .. –

ответ

4

Я столкнулся с аналогичной проблемой. Сначала я расскажу вам, что это за причина. Когда NHibernate извлекает объект из DB, он присваивает значения его реквизитам. Существует несколько реквизитов, которые имеют нулевые значения в DB, но не имеют типа Nullable в определении класса. Таким образом, NHibernate присваивает им значение по умолчанию, например. 0 для int, DateTime.MinValue для datetime и т.д. Когда вы звоните совершать по сделке, NHibernate перепроверяет значение свойств с DB значений и так реквизита, которые должны были Null значения теперь имеет значение по умолчанию, NHibernate считает, что значения были изменены и вызывает обновление.

Решение:

  1. Используйте nullable datatypes для класса реквизита по почте фиксируя их с ?, но для меня это вызывает другие проблемы.
  2. Отметьте Ваши свойства как Not Null Типы, но это не является предпочтительным в большинстве случаев.
  3. Решения, которое я использую: я задаю значение по умолчанию к реквизиту в конструкторе субъекта, поэтому вместо сохранения Null значения в DbNhibernate сохраняет значение какого-то по умолчанию, и это останавливает звонков на ненужные обновления.

Дополнительную информацию об этой проблеме вы можете найти в Google NHibernate ghostbuster.

+0

Perfect ! Несмотря на то, что он чуть больше года ... но это прекрасно описывает проблему! Все теперь использует Nullable(), и мы также отключили функциональность TrackChanges в NH –

1

NHibernate обычно проходит обновления, когда он имеет преходящие или отдельные объекты, которые он не уверен. То есть, объекты, которые не знают, имеет ли он родителя для этого, или если он не уверен, что объект грязный. Обычно это симптом плохого сопоставления где-нибудь (отсутствует Инверс на некотором родителе), или у вас нет столбцов версии или даты на ваших сущностях.