流畅的NHibernate级联删除无法正常工作

时间:2010-10-25 19:02:55

标签: c# fluent-nhibernate

我有一个使用Fluent NHibernate 1.1的简单手机目录应用程序。在应用程序中,“Person”对象具有许多“PhoneNumber”对象。我正在尝试删除一个人,我想将删除级联到PhoneNumbers。我在阅读this answer后设置了DefaultCascade.All()的约定。但是,尝试删除父对象仍会抛出异常 - 似乎NHibernate正在尝试更新子表以将父ID设置为null而不是仅删除记录:

  

{“无法删除集合:[Person.PhoneNumbers#473] [SQL:UPDATE phone_numbers SET person_id = null WHERE person_id = @ p0]”}

的InnerException:

  

{“无法将值NULL插入列'person_id',表'directory.dbo.phone_numbers';列不允许空值.UPDATE失败。\ r \ n语句已终止。”}

我的Fluent配置是:

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; }
}

子类(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();
        }
    }
}

我做错了什么?

2 个答案:

答案 0 :(得分:30)

我不确定配置Fluent部分,但我最近遇到了与ActiveRecord相同的问题。

您需要在人员方面将您的关联设置为Inverse = true

查看Getting Started文档......

我相信,你需要在Person中定义HasMany关系时设置它。看起来应该是这样的:

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

答案 1 :(得分:23)

有效;以下是每个级联选项的含义:

- 不要做任何级联,让用户自己处理它们。

save-update - 保存/更新对象时,检查关联并保存/更新任何需要它的对象(包括在多对多方案中保存/更新关联)。

删除 - 删除对象后,删除关联中的所有对象。

delete-orphan - 删除对象时,删除关联中的所有对象。除此之外,当一个对象从关联中删除而不与另一个对象(孤立对象)相关联时,也将其删除。

全部 - 当对象保存/更新/删除时,检查关联并保存/更新/删除找到的所有对象。

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();
    }
}