我有两个这样的实体(只提炼到相关内容):
public class Person {
public virtual Address Address
}
public class Address {
}
Person
与Address
具有多对一关系,或者在对象术语中,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
具有也可以参考它。
在数据库方面,没有垃圾收集的概念。对于数据库,只有一对多或多对多的关系,换句话说,就是具有子集合的父对象。回到Person
和Address
,我们发现这是从Address
到Person
的一对多关系(每个人只能有一个地址,但是地址可以属于很多人,例如共享地址的人的家庭。数据库将Address
父项和Person
视为子项集合。因此,有意义的是,删除Person
时,Address
也不应该被删除(换句话说,如果你有一个带有书籍集合的书架,删除一本书不应该删除书架)。
那么我们该如何解决这个问题呢?我们必须删除他们的子集合为空的父母。在这种情况下,应删除带有Address
空集合的Persons
。这是一个业务规则,因为没有任何内容表明Address
本身不存在,但在我正在开发的应用程序中,Address
本身就意味着什么,如果它不附加到一个人,因此应该被淘汰。但是,地址完全有可能保持孤立状态,直到其他Person
出现并引用它。
答案 0 :(得分:1)
在关系
上设置cascade =“all-delete-orphan”答案 1 :(得分:1)
在NHibernate中没有合理的方法可以做到这一点,即使您从一个(地址)方面映射关系。它等同于在其子集合之一为空时要求自动删除对象。我不会在你可能的解决方案中按照你的想法,但你是对的,这是一个商业规则。
当然,有“坏”方法可以实现这一目标。如果数据库中存在外键约束,则可以在更改引用时删除地址并吞下该异常。如果删除成功,那么它就是一个孤儿,如果没有,那么仍有人引用它。
地址通常位于关系的许多方面,即Person可以有多个地址。这是一种更好的方法。您最终会在地址表中找到重复的地址,但这会重复数据而不是重复数据。