Nhibernate以多对一关系删除父级,导致外键违规

时间:2010-11-04 19:01:02

标签: fluent-nhibernate nhibernate-mapping

我有一个可以有多个人的雇主对象:

//entities 
public class Person {
    public virtual Guid Id {get;set;}
    public virtual string Name {get;set;}
    public virtual Employer CurrentEmployer {get;set;}
}

public class Employer {
    public virtual Guid Id {get;set;}
    public virtual string Name {get;set}
    public virtual IList<Person> Employees {get;set;}
}

//person to employer mappings 
References(x => x.CurrentEmployer)
    .Cascade.All()
    .Column("CurrentEmployerId")
    .ForeignKey("FK_Person_CurrentEmployer");

//employer to person mappings
HasMany(x=> x.Employees)
    .Inverse() 
    .Cascade.All();

当我尝试删除与某人关联的雇主时,我收到“外键违规”错误。

//example
_session.Delete(oldEmployer);

如何在删除雇主之前让nHibernate使CurrentEmployerId列为空?

4 个答案:

答案 0 :(得分:1)

首先尝试清除所有CurrentEmployer,然后删除Employee

public class Employer 
{
    public virtual Guid Id {get;set;}
    public virtual string Name {get;set}
    public virtual IList<Person> Employees {get;set;}

    public void UnemployAll()
    {
        foreach(var employee in Employees)
        {
            employee.CurrentEmployer = null;
        }
        Employees = new List<Person>(); // clear it
    }
}

然后尝试以下(我认为员工(人)都应该更新),我不知道这是否会起作用,但它可能会让你开始朝着正确的方向前进。

oldEmployer.UnemployAll();
_session.Delete(oldEmplorer);

答案 1 :(得分:0)

你是否有分散的代码删除雇主?我认为通常你会在代码中只有一个地方真的删除了雇主,所以没有必要让nhibernate为你做这项工作;只需在那里更新所有引用员工的声明。

如果您确实将这些删除分散在一起,那么您可以创建一个Interceptor或Event Listener来监视表的删除并让拦截器/侦听器更新引用员工。

答案 2 :(得分:0)

尝试这样做

//employer to person mappings
HasMany(x=> x.Employees)
    .Inverse() 
    .Cascade.AllDeleteOrphan();

我没有检查,但我希望它可以帮到你。

答案 3 :(得分:0)

Oracle内置了级联删除功能(基于外键约束).Sybase没有。 根据您的数据库是否支持触发器之前和之后,您可以使用before触发器创建功能。 Sybase 12没有这个,它只有after触发器,因此在sybase上是不可能的。 Sybase 15之前有触发器,但我还没有尝试过,但它应该可以工作,基本上你手动编写before触发器来进行级联删除。

如果数据库中不存在此触发前功能,则无法进行此操作。在删除父项之前,您必须先以编程方式删除子表行。

就是这样。