NHibernate为get-only事务发送Update查询

时间:2016-06-28 11:42:41

标签: c# nhibernate

有时我在log(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; }

并映射到integer not null数据库列。

2 个答案:

答案 0 :(得分:0)

这是

的结果
  1. 脏检查和
  2. 提交时刷新
  3. 想象一下,你在DB中有专栏

    Age [int] NULL  -- Nullable column
    

    但映射说不可为空:

    <property name="Age" not-null="true" />
    

    和C#属性也不可为空

    public virtual int Age { get; set; }
    

    如果此类记录加载了 null 值,则实体的属性 Age 设置为 0

    在这种情况下...... NHiberante知道值已经改变,并尝试使用FLUSH(提交)使数据库和应用程序保持一致。这就是执行写操作的原因......只是一个例子,但在坚果壳中就是这些情况

答案 1 :(得分:0)

映射枚举的正确方法是:

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);
    }
}

这解决了我的问题。