【问题标题】:NHibernate updates not persistedNHibernate 更新不持久
【发布时间】:2014-05-06 11:50:48
【问题描述】:

我有两个这样声明的实体(非常简化):

public Test1 {
    public virtual int Id {get;set;}
    public virtual ICollection<Test2> Childs {get;set;}
}

public Test2 {
    public virtual int Id {get;set;}  
    public virtual Test1 Parent {get;set;}
    public virtual string Name {get;set;}
}    

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Test" assembly="Test">
  <class name="Test1" table="test1">
    <id name="Id" column="id_parent">
      <generator class="native" />
    </id>

    <set name="Childs" table="test2" cascade="save-update" batch-size="10" inverse="true"> 
      <key column="id_parent" not-null="true"/>
      <one-to-many class="Test.Test2, Test" />
    </set>
  </class>
</hibernate-mapping>    

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Test" assembly="Test">
  <class name="Test2" table="test2">
    <id name="Id" column="id_child">
      <generator class="native" />
    </id>

    <many-to-one name="Parent" column="id_parent" class="Test.Test1, Test" />

    <property name="Name" column="name" />
  </class>
</hibernate-mapping>

现在我想更改(第一个)孩子的 name 属性:

    var entities = Session.CreateCriteria<Test1>().List<Test1>();
    var tx = Session.BeginTransaction();
    foreach (Test1 entity in entities)
    {
        entity.Childs.First().Name = "blabla";
        Session.Update(entity);
    }
    tx.Commit();

但这不起作用。我可以在 NhProf 中看到该事务已启动,该 sql 被触发用于获取父记录,另一个用于获取子记录。但是没有为更新 name 属性触发 sql。我究竟做错了什么?我在阅读文档时尝试了不同的方法,但没有成功。

非常感谢!

【问题讨论】:

  • 尝试在foreach之后调用session.flush...
  • 提交不会刷新更改吗?我也尝试在 foreach 之后进行冲洗,但没有成功。

标签: hibernate nhibernate nhibernate-mapping hibernate-mapping


【解决方案1】:

ISession.Update 不应在上述场景中调用。您正在使用附加实体,因此会自动跟踪更改。无需显式调用 Update。

阅读此处了解更多说明:
http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-updating-detached

此外,它还取决于您的刷新模式设置为何时发生更新。尝试在上面的示例中将您的刷新模式显式设置为 Commit。这是一个刷新模式表:

自动
ISession 有时会在查询执行之前被刷新,以确保查询永远不会返回过时状态。这是默认的刷新模式。

提交
调用 Transaction.Commit() 时刷新 ISession

从不
ISession 永远不会被刷新,除非 Flush() 被应用程序显式调用。这种模式对于只读事务非常有效

所以你最终会得到这样的结果:

Session.FlushMode = FlushMode.Commit;
var entities = Session.CreateCriteria<Test1>().List<Test1>();

using(var tx = Session.BeginTransaction())
{
    foreach (Test1 entity in entities)
    {
        entity.Childs.First().Name = "blabla";
        Session.Update(entity);
    }

    tx.Commit();
}

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,并通过删除 inverse 属性解决了它。你有inverse=true。尝试将其更改为false

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多