Nhibernate 如何在Nhibernat 3.1中实现并发

Nhibernate 如何在Nhibernat 3.1中实现并发,nhibernate,concurrency,nhibernate-mapping,maping,Nhibernate,Concurrency,Nhibernate Mapping,Maping,我有一个nhibernate 3.1的项目。 我需要在项目中实现并发。 我将“版本”添加到hbm文件: <class name="Person" table="Person_Person" > <id name="Id" type="Int64" unsaved-value="0" > <generator class="native" /> </id> <version name="Version

我有一个nhibernate 3.1的项目。 我需要在项目中实现并发。 我将“版本”添加到hbm文件:

 <class name="Person" table="Person_Person"  >

    <id name="Id" type="Int64" unsaved-value="0" >
      <generator class="native" />
    </id>

    <version name="Version" />   

    <property name="FirstName" column="FirstName"
       type="String(255)" update="true" insert="true" access="property" not-null="false" />

    <property name="LastName" column="LastName"
       type="String(255)" update="true" insert="true" access="property" not-null="false" />

  </class>
我还按int类型向数据库添加了一个version字段

此实现只正确一次。 它仅在数据库中的版本值为“0”时起作用。 首次更新表中的此行后,此值更改为“1”。 但对于版本字段不是“0”(例如“1”)的下一次更新,通过以下消息引发异常:

Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [RCISP.Domain.Entities.Person#4]
我该怎么办

堆栈跟踪是:

   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)
   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)
   at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
   at NHibernate.Action.EntityUpdateAction.Execute()
   at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
   at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
   at NHibernate.Engine.ActionQueue.ExecuteActions()
   at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
   at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)

看来你做对了。它应该会起作用。请尝试以下操作:

  • 确保没有其他会话正在修改同一对象 (您获得的StaleObjectStateException可能是合法的)

  • 确保数据库本身中没有任何内容正在更新版本列(例如触发器)

  • 确保代码中没有任何内容正在更改Version属性。它仅供NHibernate使用

  • 从id映射中删除
    未保存的值=“0”
    。看看在那之后是否有效

  • 使用堆栈跟踪以及数据库和对象中的实际版本值更新答案(在保存对象之前)


  • 我相信您必须启用动态更新才能使乐观并发检查正常工作。看

    
    
    “版本”按预期工作,在我的测试中没有“动态更新”。“动态更新”不是只有在没有版本号或时间戳的版本控制中才需要吗?@Dmitry-我不知道,也许我误读了文档“如果启用动态更新,您将可以选择乐观锁定策略:”我检查了这种情况,但我的问题没有得到解决。是否更正了在更新行之后,版本值更改为“1”?更新行后不应保留“0”?对象中的版本值由nhibernate更新,并在更新期间与数据库中的值进行比较。如果你将问题隔离开来,这可能是一个好主意:编写一个独立的应用程序来重现问题。我不知道该怎么办?请进一步解释,你的代码似乎是正确的,它的作品为我。编写一个简单的控制台应用程序,使用一个映射类和版本的NHibernate。您需要隔离问题。单独使用Person类中的版本是正确的,但使用另一个类后的关系是问题。例如,按族类划分的关系(一对多)。我将版本字段添加到两个实体类和两个hbm文件中。这是正确的吗?
       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)
       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)
       at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
       at NHibernate.Action.EntityUpdateAction.Execute()
       at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
       at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
       at NHibernate.Engine.ActionQueue.ExecuteActions()
       at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
       at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
    
    <class name="Person" table="Person_Person" dynamic-update="true">