I have following entities:
public class Person {
public int Id {get;set;}
public String Name {get;set;}
public Passport Passport {get;set;}
}
public class Passport {
public int Id {get;set;}
public String PassportNo {get;set;}
// ... other properties
}
and following mapping (for Person):
ManyToOne(x => x.Passport, m =>
{
m.Column("PassportId");
m.Lazy(LazyRelation.NoLazy);
m.Unique(true);
m.Cascade(Cascade.All | Cascade.DeleteOrphans);
});
DB schema:
Table Person:
Id | Name | PassportId
Table Passport:
Id | PassportNo | other props.
As we can see, Person has it's passport, but passport has no idea about its owner, which is behaviour I want. There are 2 more assumptions:
Personcan have only 1 passport at a timePassportcan NOT exists without person
Problem is, when I assign new Passport to a Person, the old Passport remains in DB.
person.Passport = new Passport() { PassportNo = "AB 123456" };
// ...
session.Flush();
session.Commit();
SQL queries that are generated are INSERT and UPDATE (inserts new Passport, and updates Person with new Passport) - however there is no DELETE on orphaned, old passport.
The workaround I found is to set current Passport to null, call session.Flush(), and assign new Passport, like this:
person.Passport = null;
session.Flush();
person.Passport = new Passport() { PassportNo = "AB 123456" };
// ...
session.Flush();
session.Commit();
however IMO it is a hacky solution.
So, summing it up:
- am I missing something in my mapping?
- is above behaviour a bug in NH?
- can it be solved without hacky
Flush()?
After long searching for solution, I found that there is a
Joinmapping, which perfectly fits above scenario.Hope it helps someone.
More info here: http://notherdev.blogspot.com/2012/01/mapping-by-code-join.html