1

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

public class Person {
    public virtual Address Address
}

public class Address {
}

Person与 具有多对一关系Address,或者在对象方面, aPerson引用 an 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人也引用它。

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

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

4

2 回答 2

1

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

于 2010-01-09T05:26:44.640 回答
1

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

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

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

于 2010-01-10T13:05:48.937 回答