Fluent NHibernate 级联删除不起作用

发布于 2024-09-29 18:39:13 字数 2304 浏览 2 评论 0原文

我有一个使用 Fluent NHibernate 1.1 的简​​单电话目录应用程序。在应用程序中,一个“Person”对象有许多“PhoneNumber”对象。我正在尝试删除一个人,并且我想将删除级联到 PhoneNumbers。在阅读 这个答案。然而,尝试删除父对象仍然会引发异常——NHibernate 似乎正在尝试更新子表以将父 ID 设置为 null,而不是仅仅删除记录:

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

InnerException:

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

父类is:

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

我做错了什么?

I've got a simple phone directory app using Fluent NHibernate 1.1. In the app, a "Person" object has many "PhoneNumber" objects. I'm trying to delete a Person and I want to cascade deletes to PhoneNumbers. I set a convention of DefaultCascade.All() after reading this answer. However, attempting to delete the parent object still throws an exception--it appears that NHibernate is trying to update the child table to set the parent ID to null instead of just deleting the record:

{"could not delete collection: [Person.PhoneNumbers#473][SQL: UPDATE phone_numbers SET person_id = null WHERE person_id = @p0]"}

InnerException:

{"Cannot insert the value NULL into column 'person_id', table 'directory.dbo.phone_numbers'; column does not allow nulls. UPDATE fails.\r\nThe statement has been terminated."}

My Fluent config is:

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

The parent class is:

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

The child class (PhoneNumber) is:

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

My code to delete a person is:

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

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

昇り龍 2024-10-06 18:39:13

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

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

通过查看 入门 文档...

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

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

I'm not sure about configuring the Fluent part, but I recently had the same problem with ActiveRecord.

You need to set your association, on the Person side, as Inverse = true.

From looking at the Getting Started documentation...

I belive, you need to set this when defining your HasMany relationship in Person. It should look something like this:

public PersonMap()
{
    //<...SNIP...>
    HasMany(x => x.PhoneNumbers)
      .Inverse();
    //<...SNIP...>
}
当爱已成负担 2024-10-06 18:39:13

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

none - 不进行任何级联,让用户自行处理。

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

It works; Here is what each cascade option means:

none - do not do any cascades, let the users handles them by themselves.

save-update - when the object is saved/updated, check the associations and save/update any object that require it (including save/update the associations in many-to-many scenario).

delete - when the object is deleted, delete all the objects in the association.

delete-orphan - when the object is deleted, delete all the objects in the association. In addition to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.

all - when an object is save/update/delete, check the associations and save/update/delete all the objects found.

all-delete-orphan - when an object is save/update/delete, check the associations and save/update/delete all the objects found. In additional to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文