Подтвердить что ты не робот

Свободный каскад NHibernate не работает

У меня есть приложение для обычного телефона, использующее Fluent NHibernate 1.1. В приложении объект "Человек" имеет много объектов "PhoneNumber". Я пытаюсь удалить Личность, и я хочу, чтобы каскадировать удаления в PhoneNumbers. Я установил соглашение DefaultCascade.All() после прочтения этого ответа. Однако попытка удалить родительский объект по-прежнему вызывает исключение - кажется, что NHibernate пытается обновить дочернюю таблицу, чтобы установить родительский идентификатор в значение null, а не просто удалить запись:

{ "не удалось удалить коллекцию: [Person.PhoneNumbers # 473] [SQL: UPDATE phone_numbers SET person_id = null WHERE person_id = @p0]" }

InnerException:

{ "Невозможно вставить значение NULL в столбец" person_id ", table" directory.dbo.phone_numbers ", столбец не допускает нулей. Ошибка UPDATE.\r\nПриложение завершено." }

My Fluent config:

public static ISessionFactory CreateSessionFactory() {
    return Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008
            .ConnectionString(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["activeConnStr"]].ConnectionString))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Person>()
                                        .Conventions.Add(DefaultCascade.All())
                    )
        .BuildSessionFactory();
}

Родительский класс:

public class Person {
    public Person() {
        PhoneNumbers = new List<PhoneNumber>();
        EmailAddresses = new List<string>();
    }

    public virtual int Id { get; private set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string Company { get; set; }
    public virtual IList<PhoneNumber> PhoneNumbers { get; set; }
    public virtual IList<string> EmailAddresses { get; set; }
}

Класс child (PhoneNumber):

public class PhoneNumber {
    public virtual string Number { get; set; }
    public virtual PhoneNumberType NumberType { get; set; }
    public virtual Person Person { get; set; }
}

Мой код для удаления человека:

public static void DeletePerson(int id) {
    using (var session = Dalc.Instance.SessionFactory.OpenSession()) {
        using (var trans = session.BeginTransaction()) {
            session.Delete(session.Load<Person>(id));
            trans.Commit();
        }
    }
}

Что я делаю неправильно?

4b9b3361

Ответ 1

Я не уверен в настройке части Fluent, но у меня недавно была такая же проблема с ActiveRecord.

Вам нужно установить свою связь на стороне Лица как Inverse = true.

От взгляда на документацию Getting Started...

Я верю, вам нужно установить это, когда определяете свои отношения HasMany в Person. Он должен выглядеть примерно так:

public PersonMap()
{
    //<...SNIP...>
    HasMany(x => x.PhoneNumbers)
      .Inverse();
    //<...SNIP...>
}

Ответ 2

Это работает; Вот что означает каждый каскадный вариант:

none - не делайте никаких каскадов, пусть пользователи сами обрабатывают их.

сохранить-обновить - когда объект будет сохранен/обновлен, проверьте ассоциации и сохраните/обновите любой требующий его объект (включая сохранение/обновление ассоциаций во многих сценариях).

удалить - при удалении объекта удалите все объекты в ассоциации.

delete-orphan - при удалении объекта удалите все объекты в ассоциации. В дополнение к этому, когда объект удаляется из ассоциации и не связан с другим объектом (осиротевшим), также удаляйте его.

all - когда объект сохраняет/обновляет/удаляет, проверяет ассоциации и сохраняет/обновляет/удаляет все найденные объекты.

all-delete-orphan - когда объект сохраняет/обновляет/удаляет, проверяет ассоциации и сохраняет/обновляет/удаляет все найденные объекты. В дополнение к этому, когда объект удаляется из ассоциации и не связан с другим объектом (осиротевшим), также удаляйте его.

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Table("Person");

        Id(x => x.Id);
        Map(x => x.Name);

        HasMany<PhoneNumber>(x => x.PhoneNumberList)
            .KeyColumn("PersonId")
            .Cascade.All()
            .Inverse().LazyLoad();
    }
}