【问题标题】:How do you delete a referenced object when the reference changes in NHibernate?当 NHibernate 中的引用发生变化时,如何删除被引用的对象?
【发布时间】:2010-01-09 04:52:33
【问题描述】:

我有两个这样的实体(仅提炼出相关的内容):

public class Person {
    public virtual Address Address
}

public class Address {
}

PersonAddress 具有多对一关系,或者在对象方面,Person 引用 Address,并且此链接是单向的(Address 没有引用回Person)。

现在,如果我使用此代码:

// save a new person with a new address
var person = new Person();
person.Address = new Address();
person.Save();

// change the person's address and save it again
person.Address = new Address();
person.Save();

第一部分做它应该做的,它在数据库中创建一个新的Person 和一个新的Address

但是,第二部分将更新现有的Person 并创建一个新的Address,但不会删除现在孤立的第一个地址。为了让 NHibernate 认识到我正在更改对新实体的引用并自动“垃圾收集”孤立实体,我需要做什么?还是我必须手动执行此操作?

可能的解决方案

虽然我没有确凿的证据证明这确实发生了什么事,但我认为这个问题的原因是由于对象关系阻抗不匹配。在编程中,我们知道对象持有对其他对象的引用,一旦这些引用丢失,垃圾收集就会来删除那些不再有任何引用指向它们的“孤立”对象。在我提供的示例中,Person 具有对 Address 的引用,并且一旦对 Address 的引用丢失,它将被垃圾收集,假设没有其他 Persons 也引用它。

在数据库方面,没有垃圾收集的概念。对数据库来说,只有一对多或多对多的关系,或者换句话说,一个父级和一个子级的集合。回到PersonAddress,我们看到这是从AddressPerson的一对多关系(每个人只能有一个地址,但一个地址可以属于很多人,例如作为一个拥有共同地址的人的家庭)。数据库将Address 视为父级,将Person 视为子级的集合。因此,通过删除PersonAddress 也不应该被删除是有道理的(换句话说,如果你有一个书架收藏着书籍,删除一本书不应该删除书架)。

那么我们该如何解决这个问题呢?我们将不得不删除其子集合为空的所有父级。在这种情况下,应删除具有空集合PersonsAddress。这是一个业务规则,因为没有任何内容表明 Address 不能单独存在,但是在我正在开发的应用程序中,如果 Address 本身没有附加到一个人身上,那么它本身就没有任何意义,因此应该被淘汰。但是,在其他 Person 出现并引用它之前,该地址完全有可能保持孤立状态。

【问题讨论】:

    标签: nhibernate nhibernate-mapping many-to-one


    【解决方案1】:

    在关系上设置 cascade="all-delete-orphan"

    【讨论】:

    • 我已经试过了。虽然它适用于删除父实体(在本例中为 Person 对象),但如果您将子实体更改为新实体,它就不起作用。旧的将保持孤儿状态。
    【解决方案2】:

    在 NHibernate 中没有合理的方法来执行此操作,即使您从一侧(地址)映射关系也是如此。这相当于要求一个对象在其子集合之一为空时自动删除。在您可能的解决方案中,我没有遵循您的想法,但您是正确的,这是一条业务规则。

    当然,有一些“坏”的方法可以做到这一点。如果数据库中有外键约束,您可以在更改引用时删除地址并吞下异常。如果删除成功,那么它是一个孤儿,如果没有,那么仍然有 Persons 引用它。

    地址通常位于关系的多方面,即人可以有多个地址。这是,imo,一个更好的方法。您最终会在地址表中得到重复的地址,但这作为重复数据而不是重复数据。

    【讨论】:

    • 重复数据和重复数据有什么区别?
    猜你喜欢
    • 2022-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多