【问题标题】:NHibernate doesn't remove unuseful record when update child collectionsNHibernate 在更新子集合时不会删除无用的记录
【发布时间】:2014-04-04 01:42:56
【问题描述】:

当我使用 Nhibernate 3 更新子级时,子级中删除的项目不会从数据库中删除。

案例描述如下

class Parent {
   string Id;
   string Name;
   IList Children;
}
class Child {
   int ChildId;
   string Name;
   string Value;
   Parent parent;
}

hdm 映射文件如下所示 父级.hdm.xml

<bag name="Children" table="ClientsExt" inverse ="true" cascade="all-delete-orphan" lazy="false">
  <key column="ChildId"/>
  <one-to-many class="XXXX.Child, XXX"/>
</bag>

Child.hdm.xml

<many-to-one name="Parent" column="Id" class="XXXX.Parent, XXX" not-null="true"/>   

假设现有的父级关联了数据库中的一组子级

Parent Table
Id = "P1", Name = "Test"
Child Table
ChildId = 1, Id="P1", Name = "N1", Value = "V1"
ChildId = 2, Id="P1",Name = "N1", Value = "V2"
ChildId = 3, Id="P1",Name = "N2", Value = "V3"

就我而言,我需要部分更新孩子。 在更新的Parent中需要更新记录2 将 ChildId = 2 的值设置为 value = "NEWVALUE" 删除 ChildId = 1,Id="P1",Name = "N1",Value = "V1" 并且 ChildId 3 将被保留。

所以我首先从数据库中获取父级,

var entity = _parentRepo.getById("P1");

var children = entity.Children;

var updatedChildren = children.ToList<Child>;

var tmpList = new List<Child>();

//biz means the business logic object which contains update info

if (biz.N1.Count > 0){

     var existN1 = children.Where(x=>x.Name.Equals("N1")).Select(y=>y.ChildId);

     int count = existN1.Count;

     int index = 0;

     biz.N1.ForEach(x=>{

         if(index < count){
            tmpList.Add(new Child(){ Id = existN1[index],Name="N1",Value="newValue",Parent = entity });
         }else{
           tmpList.Add(new Child(){ Name="N1",Value="newValue",Parent = entity });
         }
     });

  updatedChildren.RemoveAll(x=>x.Name.Equals("N1"));

  updateChildren.AddRange(tmpList);
}

entity.Children = updateChildren;
//Save the entity

但是,在数据库中,记录 2 将值更新为“NEWVALUE”,但没有删除 ChildId = 1, Id="P1", Name = "N1", Value = "V1" 。 为什么?

提前致谢。

【问题讨论】:

  • 更改最后几行代码,生活变得轻松。 entity.Children.Clear(); updateChildren.ForEach(x=&gt;entity.Children.Add(x)

标签: nhibernate cascade


【解决方案1】:

发生了什么,是上面的代码打破了session的原则,分裂了链条。每当我们希望 NHibernate 做出明智的决定时,我们必须始终关注底层的东西。这不符合:

var children = entity.Children;
var updatedChildren = children.ToList<Child>; // a brand new NHibernate-detached coll
...
// operations out of the scope of the NHiberante session
...
entity.Children = updateChildren; // broken chain of information

在幕后,NHibernates 将自己的智能集合放入entity.Children 属性中。它正在跟踪有关更改的信息(已删除元素,已更改..),因此如果要求它保留更改... NHibernate 知道...

如果我们放入全新的、断开连接的集合,NHibernate 几乎无法发现缺少某些元素。没办法如何发出DELETE。

解决方案:始终使用 entity.Children 引用。然后我们会得到我们需要的......

【讨论】:

  • 酷,非常感谢。现在我更改了代码,它可以工作了。谢谢一百万。
  • 很高兴看到这一点。享受 NHibernate,令人惊叹的工具 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
  • 2020-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多