Nhibernate Flush causa actualizaciones donde no debería haber ninguna
fluent nhibernate mapping (2)
Estoy usando el patrón Repo, y he configurado pruebas para replicar una solicitud HTTP que entra y que luego produce una eliminación en una unidad de trabajo una vez que se ha completado una prueba.
Parece que después de ejecutar una declaración HQL y luego llamar a la función de distribución (que a su vez llama a color) está causando una actualización en varios elementos.
Muy extraño: ¿alguien se ha encontrado con esto antes?
Aquí está mi declaración HQL y su ejecución:
_session.CreateQuery("select distinct t from TaskEntity as t").List<T>()
Retiré esto a su forma más simple y observo que la declaración HQL no está directamente en CreateQuery.
Aquí está el rastro de la pila que estoy obteniendo:
yo
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
Normalmente NHibernate ejecuta actualizaciones cuando tiene entidades transitorias o independientes de las que no está seguro. Es decir, entidades que no sabe si tiene un padre para que lo administre o si no está seguro de que la entidad está sucia. Esto suele ser un síntoma de un mal mapeo en algún lugar (un Inverse faltante en algunos padres) o no tiene una columna Versión o Fecha en sus entidades.
Enfrenté un problema similar. Primero te diré qué causa esto. Cuando NHibernate
recupera una entidad del DB
le asigna valores. Hay pocos accesorios que tienen valores nulos en la base de DB
pero no son de tipo Nullable
en la definición de la clase. Entonces, NHibernate
les asigna un valor predeterminado, por ej. 0
para int
, DateTime.MinValue
para datetime
etc. Cuando llama a commit en la transacción, NHibernate
vuelve a verificar los valores de las propiedades con valores DB
y dado que los accesorios que deberían tener valores Null
ahora tienen un valor predeterminado, NHibernate
cree que los valores han sido cambiado y causa una actualización.
Solución:
- ¿Utiliza
nullable datatypes
denullable datatypes
para los accesorios de tu clase mediante la fijación de ellos con?
pero para mí esto está causando otros problemas. - Asigne sus propiedades como Tipos
Not Null
pero esto no es preferible en la mayoría de los casos. - La solución que estoy usando: estoy asignando valores predeterminados a los puntales en el constructor de la entidad, por lo que en lugar de guardar los valores
Null
en elDb
Nhibernate
guarda algún valor predeterminado y esto detiene las llamadas a actualizaciones innecesarias.
También puede buscar en Google NHibernate ghostbuster
para obtener más información sobre este problema.