我有以下问题。
我有一个包含子对象集合的父类。
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会这样做? 有人解释并可以帮我解决这个问题吗?
答案 0 :(得分:2)
NHibernate中SQL语句的顺序为predefined:
SQL语句按以下顺序发布
- 保存
所有实体插入,按相同顺序对应的对象 使用ISession.Save()
所有实体更新
所有收集删除
所有集合元素删除,更新和插入
所有收集插入
- 删除
所有实体删除,按相同顺序对应的对象 使用ISession.Delete()
NHibernate认为新的child实例实际上是一个新实体。所以它首先插入它,违反了数据库约束。这意味着您有两个选择:
1)在移除后和添加孩子之前立即冲洗。
2)稍微改变你的设计,这样你就可以编辑孩子而不是删除/添加。这似乎更合乎逻辑,因为看起来Child是一个由Name标识的实体。目前尚不清楚为什么要实际添加和删除相同的孩子:
Child child = parent.GetChildByName("Child1");
child.DoSomething();
或者像这样:
parent.DoSomethingWithChild("Child1");
P.S。我假设您的Child.Equals实现使用了名称,在您的映射中,您有<one-to-many class="Child" />
,而不是<one-to-many class="Parent" />
。这可能只是一个错字。