NHibernate删除并添加ParentClass的ChildCollection

发布于 12-02 15:13 字数 1423 浏览 2 评论 0原文

我有以下问题。

我有一个包含子对象集合的父类。

 public class Parent{

      int _id;
      IList<Child> _childs = new List<Child>();


      public IList<Child> Childs {get;}
 }

 public class Child{

      int _id;
      string _name;
      Parent _parent;

      protected Child(){}

      public Child(Parent parent, string name){
         _parent = parent;
         _name = name;
      }
 }

这些类使用 nhibernate 映射到数据库,其中 tblChild.colName 列具有唯一索引。

 // Parent
 <bag name="_childs" access="field" cascade="all-delete-orphan" inverse="true">
    <key column="ParentId" />
    <one-to-many class="Parent" />
 </bag>

// Child
<many-to-one name="_parent" column="ParentId" cascade="none" access="field">

我的问题: 下面的代码由于唯一索引而抛出异常:

 Parent parent = new Parent();
 Child child1 = new Child(parent, "Child1");
 Child child2 = new Child(parent, "Child2");
 Child child3 = new Child(parent, "Child3");

 parent.Childs.Add(child1);
 parent.Childs.Add(child2);
 parent.Childs.Add(child3);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

 Child child4 = new Child(parent, "Child1"); // Duplicate Name
 parent.Childs.Remove(child1);
 parent.Childs.Add(child4);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

异常的原因是NHibernate先插入child4,然后删除child1。 NHibernate 为什么要这样做? 有人解释并可以帮助我解决这个问题吗?

I have the following problem.

I have a parent class with a collection of child objects.

 public class Parent{

      int _id;
      IList<Child> _childs = new List<Child>();


      public IList<Child> Childs {get;}
 }

 public class Child{

      int _id;
      string _name;
      Parent _parent;

      protected Child(){}

      public Child(Parent parent, string name){
         _parent = parent;
         _name = name;
      }
 }

The classes are mapped with nhibernate for database where the column tblChild.colName has a unique index.

 // Parent
 <bag name="_childs" access="field" cascade="all-delete-orphan" inverse="true">
    <key column="ParentId" />
    <one-to-many class="Parent" />
 </bag>

// Child
<many-to-one name="_parent" column="ParentId" cascade="none" access="field">

My problem:
The following code throw exception because of unique index:

 Parent parent = new Parent();
 Child child1 = new Child(parent, "Child1");
 Child child2 = new Child(parent, "Child2");
 Child child3 = new Child(parent, "Child3");

 parent.Childs.Add(child1);
 parent.Childs.Add(child2);
 parent.Childs.Add(child3);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

 Child child4 = new Child(parent, "Child1"); // Duplicate Name
 parent.Childs.Remove(child1);
 parent.Childs.Add(child4);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

The reason for the exception is that NHibernate first inserts child4 and then removes child1. Why does NHibernate do so?
Someone an explaination and can help me resolving this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不在是我2024-12-09 15:13:14

SQL 语句的顺序是在 NHibernate 中预定义的

SQL语句按以下顺序发出

  • 所有实体插入,与相应对象的顺序相同
    使用 ISession.Save() 保存

  • 所有实体更新

  • 所有集合删除

  • 所有集合元素删除、更新和插入

  • 所有集合插入

  • 所有实体删除,按相应对象的相同顺序
    使用 ISession.Delete() 删除

NHibernate 认为 child 的新实例实际上是一个新实体。因此它首先插入它,这违反了您的数据库约束。这意味着您有两个选择:

1)在删除之后和添加子项之前立即刷新。

2)稍微改变一下你的设计,这样你就可以简单地编辑子项,而不是删除/添加。这看起来更合乎逻辑,因为看起来 Child 是一个由 Name 标识的实体。目前尚不清楚为什么您实际上添加和删除相同的子项:

Child child = parent.GetChildByName("Child1");
child.DoSomething();

或像这样:

parent.DoSomethingWithChild("Child1");

PS 我假设您的 Child.Equals 实现使用名称,并且在您的映射中您有 ;,而不是。这可能只是一个错字。

The order of SQL statements is predefined in NHibernate:

The SQL statements are issued in the following order

  • all entity insertions, in the same order the corresponding objects
    were saved using ISession.Save()

  • all entity updates

  • all collection deletions

  • all collection element deletions, updates and insertions

  • all collection insertions

  • all entity deletions, in the same order the corresponding objects
    were deleted using ISession.Delete()

NHibernate thinks that new instance of child is actually a new entity. So it inserts it first, violating your database constraint. It means that you have two options:

1) Flush immediately after removing and before adding child.

2) Change your design a bit so that instead of Remove/Add you simply edit the child. This seems more logical because it looks like Child is an entity that is identified by Name. It is not clear why you actually adding and removing same child:

Child child = parent.GetChildByName("Child1");
child.DoSomething();

or like this:

parent.DoSomethingWithChild("Child1");

P.S. I assume your Child.Equals implementation uses name and in your mapping you have <one-to-many class="Child" />, not <one-to-many class="Parent" />. This is probably just a typo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文