Some help on the following situation would be much appreciated...
I've got two tables that on the face of it have a normal 1 to many
relationship, i.e. records in TableA have a reference to a record in
TableB, however the relationship is optional because the field can be
null, i.e. zero or 1 to many. relationship
I want to model two distinct types of object for TableA, those with
that foreign relationship and those without (as conceptually the
business entities are different enough ). It would make sense to have
a ClassMap and SubClassMap for those 2 entities, where SubClassMap is
discriminated on the column that has the optional foreign relationship
(DiscriminateSubColumClassesOnColumn)
But, 2 problems:
1) In SubClassMap, how do I discriminate on "Not Null" for that field,
so that the sub class only leads to objects with that foreign
relationship.
2) How do I ensure the parent class only leads to objects that have
Null in that field.
For 2), I can only really see that I'd have an abstract base and 2
subclasses, but one of the subclasses wouldn't derive any new data,
it's just a concrete version of the abstract base.
Anyway, I hope that all makes sense, I'm very new to NHibernate and
Fluent, so apologies if I've missed some very obvious concepts.
Thanks
Boz
I suggest you move away from mapping this with inheritance. You can
still use inheritance to achieve the desired polymorphic behavior
based on the whether the FK is null or not, via delegation:
public class StaffMember
{
public StaffMember Manager { get; set; }
public void PerformCalculationOne()
{
InnerCalculator.PerformCalculationOne();
}
public void PerformCalculationTwo()
{
InnerCalculator.PerformCalculationTwo();
}
private StaffCalculator InnerCalculator
{
get { return Manager == null ? new NoManagerCalculator() : new
DefaultCalculator(); }
}
}
2009/12/21 Boz <jjkbo...@yahoo.com>:
> --
>
> You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group.
> To post to this group, send email to fluent-n...@googlegroups.com.
> To unsubscribe from this group, send email to fluent-nhibern...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en.
>
>
>
I'm not sure I fully understand your response or whether I've phrased
my question wrong. I see what you mean about not wanting to have
objects in an invalid state at runtime, however wouldn't that always
be the case for when you use DiscriminateSubClassesOnColumn? i.e. are
you saying the discriminator mapping should never be used?
In my particular case the two classes are different and instances are
not intended to be switched, even though they get their data from the
same table. So, although records in TableA can be of TypeA or TypeB,
there's no intention that setting a property of TypeA would make it a
TypeB or viceversa, and the class and mapping wouldn't permit that.
Also, the use of delegating the behaviour... did you intend that I
would have just TypeA mapping to TableA, and then have two "behaviour"
classes? In my case, the behaviours are not polymorphic and in some
instances of the class the properties and behaviour would not be
implemented.
So I'm not sure if we're talking about different things here or if I
have just got this all wrong.
A colleague has found that it is possible to achieve a "not null"
subclass discrimination in nHibernate by use of formulas:
http://stackoverflow.com/questions/1664936/nhibernate-inheritance-discriminator-value
<discriminator formula="case when discriminatorID = '' then 1 else 2
end"/>
and Fluent supports DiscriminatorPart.Formula(string sql), i.e.:
DiscriminateSubClassesOnColumn("discriminatorID")
.Formula("case when discriminatorID = '' then 1 else 2 end");
So I can achieve what I need to but I need to understand if its right
to, based on your points in your response.
Thanks
Boz
On Dec 30 2009, 11:07 am, Paul Batum <paul.ba...@gmail.com> wrote:
> This idea sounds dangerous to me. You can't have an object "change
> class" at runtime, so what is supposed to happen when your
> relationship changes (either a record with a NULL gets a valid FK or
> vice versa, the FK is nulled out)? Suddenly the state of your object
> no longer makes sense.
>
> I suggest you move away from mapping this with inheritance. You can
> still use inheritance to achieve the desired polymorphic behavior
> based on the whether the FK is null or not, via delegation:
>
> public class StaffMember
> {
> public StaffMember Manager { get; set; }
>
> public void PerformCalculationOne()
> {
> InnerCalculator.PerformCalculationOne();
> }
>
> public void PerformCalculationTwo()
> {
> InnerCalculator.PerformCalculationTwo();
> }
>
> private StaffCalculator InnerCalculator
> {
> get { return Manager == null ? new NoManagerCalculator() : new
> DefaultCalculator(); }
> }
>
> }
>
> 2009/12/21Boz<jjkbosw...@yahoo.com>:
Boz,
If TypeA always has null for the collection property, can you not just move the property to the subclass TypeB, then all your problems go away:
class TypeA {
int Id;
string Name;
}
class TypeB : TypeA {
IList<Child> Children;
}
class Child {
....
}
class TypeAClassMap : ClassMap<TypeA>{
public TypeAClassMap() {
Id(x=>x.Id);
Map(x=>x.Name);
DiscriminateSubclassesOnColumn(“type”)
}
}
class TypeBClassMap : SubClassMap<TypeB>{
public TypeBClassMap() {
HasMany(x=>x.Children);
I think maybe I misunderstood your initial post somewhat, so I
apologise for the confusion. My mistake was thinking that the
relationship could be mutated over time (start off null, then
assigned, then maybe nulled out). Given that this is not the case, I
think Martin's suggestion here is a good one - discriminate with a
dedicated column (he called it "type" in his example), and then map
the relationship only in the subclass.This sits better with me, though
I appreciate that if you have no control over the database schema then
it is not an option. If you do have to work with the given schema,
then the discriminator with a formula is probably the way to go.