【问题标题】:Fluent NHibernate cascade delete not workingFluent NHibernate 级联删除不起作用
【发布时间】:2011-04-30 09:28:23
【问题描述】:

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

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

内部异常:

{"无法将值 NULL 插入列 'person_id',表 'directory.dbo.phone_numbers';列不允许空值。更新失败。\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();
        }
    }
}

我做错了什么?

【问题讨论】:

    标签: c# fluent-nhibernate


    【解决方案1】:

    我不确定如何配置 Fluent 部分,但我最近在使用 ActiveRecord 时遇到了同样的问题。

    您需要在 Person 方面将关联设置为 Inverse = true

    通过查看Getting Started 文档...

    我相信,您需要在 Person 中定义 HasMany 关系时进行设置。它应该看起来像这样:

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

    【讨论】:

    【解决方案2】:

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

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

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

    delete - 当对象被删除时,删除关联中的所有对象。

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

    【讨论】:

    • +1 以获得我见过的cascade 选项的最简明解释。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 2013-03-03
    相关资源
    最近更新 更多