I have two entities like so (distilled to only what's relevant):
public class Person {
public virtual Address Address
}
public class Address {
}
Person
has a many-to-one relationship with Address
, or in object terms, a Person
references an Address
, and this link is uni-directional (Address
does not have a reference back to Person
).
Now, if I use this code:
// 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();
The first part does what it's supposed to, it creates a new Person
and a new Address
in the database.
However, the second part will update the existing Person
and create a new Address
, but it doesn't delete the now-orphaned first address. What do I have to do in order to get NHibernate to recognize that I'm changing the reference to a new entity and automatically 'garbage collect' the orphaned entity? Or do I have to do this manually?
Possible Solution
Although I don't have conclusive evidence that this indeed what's going on, I think the reason for this problem is because of the object-relational impedance mismatch. In programming, we know that objects hold references to other objects, and once those references are lost, garbage collection will come and delete those 'orphaned' objects that no longer have any references pointing to them. In the example I provided, Person
has a reference to Address
, and once the reference to Address
is lost, it will get garbage collected, assuming no other Persons
have a reference to it as well.
On the database side, there is no concept of garbage collection. To the database, there is only one-to-many or many-to-many relationships, or in other words, a parent with a collection of children. Going back to Person
and Address
, we see that this is a one-to-many relationship from Address
to Person
(each person can only have one address, but an address can belong to many people, such as a household of people that share a common address). The database considers the Address
the parent and the Person
as a collection of children. Thus, it makes sense that by deleting a Person
, the Address
should not be deleted as well (put another way, if you have a bookshelf with a collection of books, deleting a book should not delete the bookshelf).
So how do we fix this? We'll have to delete any parents where their child collections are empty. In this case, an Address
with an empty collection of Persons
should be deleted. This is a business rule, as nothing states that an Address
cannot exist by itself, but in the application I'm developing, an Address
by itself means nothing if it's not attached to a person, and thus should be eliminated. However, it's entirely possible for the address to remain in an orphaned state until some other Person
comes along and references it.