NHibernate正在发送get-only事务的更新查询
本文关键字:事务 更新 查询 get-only NHibernate | 更新日期: 2023-09-27 17:52:15
有时我在日志(NHibernate.SQL(中看到,当我提交事务时,此代码会导致实体的update
SQL查询。
using (ISession session = SessionFactory.OpenSession())
{
using (session.BeginTransaction())
{
entity = session.Get<E>(id);
session.Transaction.Commit();
}
}
为什么会发生这种情况?
堆栈跟踪:
at NHibernate.AdoNet.Util.SqlStatementLogger.LogCommand(String message, IDbCommand command, FormatStyle style) in p:'nhibernate-core'src'NHibernate'AdoNet'Util'SqlStatementLogger.cs:line 56
at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd) in p:'nhibernate-core'src'NHibernate'AdoNet'AbstractBatcher.cs:line 191
at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation) in p:'nhibernate-core'src'NHibernate'AdoNet'NonBatchingBatcher.cs:line 40
at 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) in p:'nhibernate-core'src'NHibernate'Persister'Entity'AbstractEntityPersister.cs:line 2776
at 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) in p:'nhibernate-core'src'NHibernate'Persister'Entity'AbstractEntityPersister.cs:line 2702
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session) in p:'nhibernate-core'src'NHibernate'Persister'Entity'AbstractEntityPersister.cs:line 2957
at NHibernate.Action.EntityUpdateAction.Execute() in p:'nhibernate-core'src'NHibernate'Action'EntityUpdateAction.cs:line 79
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in p:'nhibernate-core'src'NHibernate'Engine'ActionQueue.cs:line 136
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in p:'nhibernate-core'src'NHibernate'Engine'ActionQueue.cs:line 125
at NHibernate.Engine.ActionQueue.ExecuteActions() in p:'nhibernate-core'src'NHibernate'Engine'ActionQueue.cs:line 171
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in p:'nhibernate-core'src'NHibernate'Event'Default'AbstractFlushingEventListener.cs:line 241
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) in p:'nhibernate-core'src'NHibernate'Event'Default'DefaultFlushEventListener.cs:line 20
at NHibernate.Impl.SessionImpl.Flush() in p:'nhibernate-core'src'NHibernate'Impl'SessionImpl.cs:line 1507
at NHibernate.Transaction.AdoTransaction.Commit() in p:'nhibernate-core'src'NHibernate'Transaction'AdoTransaction.cs:line 193
更新后的属性看起来像:
public virtual MyEnum MyProperty { get; set; }
并映射到CCD_ 2数据库列。
这是的结果
- 脏检查和
- 提交时刷新
想象一下,DB 中有一列
Age [int] NULL -- Nullable column
但映射显示不能为空:
<property name="Age" not-null="true" />
并且C#属性也是不可为空的
public virtual int Age { get; set; }
如果此类记录加载了null
值,则实体的属性Age
将设置为0。
在这种情况下。。。NHiberante知道值已经改变,并尝试在FLUSH(提交(上使DB和应用程序对齐。这就是为什么要执行写操作。。。这只是一个例子,但在坚果壳中,
映射枚举的正确方法是:
public class EnumConvention : IPropertyConvention, IPropertyConventionAcceptance
{
public void Apply(IPropertyInstance instance)
{
instance.CustomType(instance.Property.PropertyType);
}
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property != null);
criteria.Expect(x => x.Type.IsEnum);
}
}
这解决了我的问题。