Nhibernate удаляет родителя в отношениях «многие к одному», вызывая нарушение внешнего ключа - PullRequest
2 голосов
/ 04 ноября 2010

У меня есть объект Employer, в котором может быть несколько людей:

//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 ]

1 голос
/ 10 декабря 2010

попробуйте сначала очистить все CurrentEmployer, а затем удалить сотрудника

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);
0 голосов
/ 16 декабря 2010

Oracle имеет встроенную функцию каскадного удаления (на основе ограничений внешнего ключа). В Sybase нет.В зависимости от того, поддерживает ли ваша база данных триггеры до и после, вы можете создать функциональность с триггерами до.Sybase 12 не имеет этого, он имеет только после триггеров, так что это невозможно на Sybase.Sybase 15 имеет триггеры до, но я еще не пробовал, но он должен работать, в основном вы пишете триггер до вручную, чтобы выполнить каскадное удаление.

Если в вашей базе данных нет функции триггера до триггера, это невозможно.Вам придется программно удалить строки дочерней таблицы, прежде чем удалять родителей.

Вот так.

0 голосов
/ 16 декабря 2010

Попробуйте сделать это

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

Я не проверял, но надеюсь, что это может вам помочь.

0 голосов
/ 04 ноября 2010

Есть ли у вас разбросанный код, который удаляет работодателей?Я думаю, что обычно у вас есть только одно место в коде, которое удаляет работодателей, поэтому на самом деле не нужно, чтобы nhibernate выполнял эту работу за вас;Просто сделайте там заявление, которое обновляет всех сотрудников, на которые делается ссылка.

Если вы действительно разбросали все эти удаления, то вы можете создать Interceptor или Event Listener, который наблюдал бы за удалениями в таблице, и иметь перехватчик / Listener.обновить ссылки сотрудников.

...