NHibernate级联=“all-delete-orphan"正在删除非孤立行
本文关键字:删除 级联 all-delete-orphan quot NHibernate | 更新日期: 2023-09-27 18:12:30
当使用cascade="all-delete-orphan"时,NHibernate正在删除一个不是孤儿的子行——它只是被移动到一个新的父行。
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
// Get the store we're moving him to
Store newStore = session.QueryOver<Store>().Where(...).SingleOrDefault();
// Get existing employee
Employee jack = session.QueryOver<Employee>().Where(...).SingleOrDefault();
// Do the move
jack.Store.Staff.Remove(jack);
jack.Store = newStore;
jack.Store.Staff.Add(jack);
transaction.Commit();
}
}
当commit发生时,生成一条DELETE语句从数据库中删除'jack'。如果"杰克"实际上是孤儿,那么这种行为就说得通了,但现在他应该高兴地被分配到他的新店。
如果我将级联更改为"all",则会生成预期的UPDATE语句,并且'jack'会按照预期愉快地重新分配。但是,这会导致真正的孤立行保留在数据库中,这是不可接受的。
这是一个bug还是有什么我做错了?
下面是类:
public class Store
{
public virtual Guid Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<Employee> Staff { get; set; }
}
public class Employee
{
public virtual Guid Id { get; private set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual Store Store { get; set; }
}
和FluentNHibernate映射:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Store);
}
}
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id).GeneratedBy.Guid();
Map(x => x.Name);
HasMany(x => x.Staff)
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
经过更多的测试,这似乎是一个bug,因为加载对象的顺序改变了结果(注意,在这两种情况下,Move Employee都是如上所述):
1)加载存储B,加载存储A,在A中查找员工,将员工移动到B==> Employee被删除(不抛出异常,不重新插入Employee)
2)加载存储A,加载存储B,在A中查找员工,将员工移动到B==> ObjectDeletedException(删除的对象将被级联(从关联中删除对象)重新保存)
第二种情况似乎是@Cole W提到的场景,在这里和这里讨论过,这是NHibernate中已知的孤儿处理的限制。
然而,第一种情况似乎是一个错误。在我的理解中,不应该有这样的场景:对象加载的顺序改变了NHibernate对数据库的更改。这似乎是一个可能导致数据丢失的错误。
更新2
考虑到不一致的行为依赖于加载顺序和潜在的数据丢失,我已经将其作为NHibernate JIRA中的一个bug记录下来。这个bug报告有完整的代码和映射来演示这个问题。
这似乎是其他使用NHibernate的人经常遇到的问题。看看这些文章是否对你有帮助。
查看这篇文章:Fluent NHibernate异常在集合之间移动对象
这篇文章中还有Fabio Maulo的文章链接:
http://fabiomaulo.blogspot.com/2009/09/nhibernate-tree-re-parenting.html
这个问题很可能是由于覆盖了多个引用而没有告诉NHibernate发生了什么
当我们等待更新的Q时(请参阅我对缺失的Staff属性的评论),我建议更改您的查询,以便您直接询问Store
,而不是在Employee对象上使用Store导航器。从该Store.Staff
集合中删除jack,发出session.SaveOrUpdate(store)
,然后尝试将jack.Store
引用覆盖到新引用(在提交事务之前发出另一个SaveOrUpdate
)