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数据库列。

NHibernate正在发送get-only事务的更新查询

这是的结果

  1. 脏检查和
  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);
    }
}

这解决了我的问题。