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级联=“all-delete-orphan"正在删除非孤立行

这似乎是其他使用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)