Fluent NHibernate SubClass syntax changes
I’ve just committed a breaking change to Fluent NHibernate (as of r184), which I thought I’d document here for anyone interested; it’s a reworking of the subclass syntax.
Mapping multiple subclasses with the same parent wasn’t a very fluent affair, and it was pretty wordy too. You can see a comparison of the old and new syntaxes below.
Before
var discriminator = DiscriminateSubClassesOnColumn<string>("Type");
discriminator.SubClass<B>()
.IdentifiedBy("bID")
.MapSubClassColumns(m =>
{
m.Map(x => x.BProperty);
});
discriminator.SubClass<C>()
.IdentifiedBy("cID")
.MapSubClassColumns(m =>
{
m.Map(x => x.CProperty);
});
After
DiscriminateSubClassesOnColumn("Type")
.SubClass<B>(m =>
{
m.Map(x => x.BProperty);
})
.SubClass<C>(m =>
{
m.Map(x => x.CProperty);
});
Much nicer! The changes you can see here are:
DiscriminateSubClassesOnColumn
now assumes your discriminator is astring
if you don’t specify a typeSubClass
defaults to using the subclass type name as a discriminator valueIdentifiedBy
andMapSubClassColumns
are now merged intoSubClass
as overloads.
Nested subclasses were never really supported in Fluent NHibernate, but they were hackable. You could abuse DiscriminateSubClassesOnColumn
to let you trick it into creating nested classes. This worked but it led to some really ugly mapping code (and a nasty hack in the Fluent NHibernate codebase). I’ve given some loving to this area and have managed to really sweeten-up the syntax.
Before
DiscriminateSubClassesOnColumn<string>("Type")
.SubClass<B>()
.IdentifiedBy("bID")
.MapSubClassColumns(m =>
{
m.Map(x => x.BProperty);
m.DiscriminateSubClassesOnColumn<string>("Type")
.SubClass<C>()
.IdentifiedBy("cID")
.MapSubClassColumns(m =>
{
m.Map(x => x.CProperty);
});
});
After
DiscriminateSubClassesOnColumn("Type")
.SubClass<B>(m =>
{
m.Map(x => x.BProperty);
m.SubClass<C>(m =>
{
m.Map(x => x.CProperty);
});
});
The changes in this one are:
SubClass
can now be used within subclasses without having to reuseDiscriminateSubClassesOnColumn
All in all, these changes serve to make mapping subclasses in Fluent NHibernate a little bit neater.
Update
As requested, here are the domain entities that the above mappings represent.
Two subclasses with shared parent
public class A
{}
public class B : A
{
public virtual string BProperty { get; set; }
}
public class C : A
{
public virtual string CProperty { get; set; }
}
Subclass of a subclass
public class A
{}
public class B : A
{
public virtual string BProperty { get; set; }
}
public class C : B
{
public virtual string CProperty { get; set; }
}