NHibernate更新不会持久化

时间:2014-05-06 11:50:49

标签: hibernate nhibernate nhibernate-mapping hibernate-mapping

我有两个这样的实体(很简化):

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>

现在我想更改(第一个)子项的名称属性:

    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。我究竟做错了什么?我在阅读文档时尝试了不同的事情,但没有成功。

非常感谢提前!

2 个答案:

答案 0 :(得分:0)

不应在上面的场景中调用

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

请阅读此处以获得进一步说明:
http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-updating-detached

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

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

<强>提交
调用Transaction.Commit()时,将刷新ISession

<强>从不
除非应用程序显式调用Flush(),否则永远不会刷新ISession。此模式对于只读事务非常有效

所以你最终会得到这样的东西:

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

答案 1 :(得分:0)

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