NHibernate Discriminated Subclasses of a Joined-Subclass
Asked Answered
E

2

6

Here's my heirarchy:

class abstract Entity { /*members*/ } // mapped to entity table
class abstract User : Entity { /*members*/ } // mapped to user table

class Employee : User { /*no members*/ } // no table, discriminator = "E"
class Contractor : User { /*no members*/ } // no table, discriminator = "C"

Here's my mappings in two separate hbm files:

<class name="Entity" table="entity" xmlns="urn:nhibernate-mapping-2.2">
  <id name="Id" column="id">
    <generator class="guid.comb" />
  </id>
  <property ... />
</class>

<joined-subclass name="User" extends="Entity" table="user">
  <key column="id" />
  <discriminator column="type" />
  <property ... />
  <subclass name="Employee"   discriminator-value="E" />
  <subclass name="Contractor" discriminator-value="C" />
</joined-subclass>

The following is the exception I get:

MappingException: XML validation error: The element 'joined-subclass' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'discriminator' in namespace 'urn:nhibernate-mapping-2.2'.

What am I missing? Can you not map a discriminated subclass hierarchy of a joined-subclass?

Excrescent answered 24/1, 2011 at 17:38 Comment(0)
W
2

What you want to do is not currently possible.

Check http://www.nhforge.org/doc/nh/en/index.html#inheritance for allowed constructs.

Wiggins answered 24/1, 2011 at 20:17 Comment(7)
So if I understand this right, I can't mix different inheritance strategies? Basically, if every class ultimately descends from a base-class like "Entity", then I have to pick one strategy and that's it for whole hierarchy. I understand not being able to mix at the same level, but is there any chance this will be supported for different levels in the future?Excrescent
@Travis, is there a reason you want to have a table for Entity?Electrocorticogram
Yes; there are 6 fields that are common to all my entities [Id, IsActive, DateCreated, Creator, DateModified, Modifier]. But even if I didn't need Entity, User would take its place in a similar situation if I needed to extend Contractor or Employee.Excrescent
You usually never map the "Entity" class, so that's not an issue. And no, you can't arbitrarily mix strategies beyond what's supported according to the docs. Since it's not a very common need, I doubt it will be supported unless you can provide a fully tested patch for that, which is likely to be really hard, if possible at all, to code.Wiggins
Disregarding your "never do this or that" comment (I could call Entity something else that is good base class name), the problem is isomorphic to the situation that could always occur when you have both child and grandchild descendant classes where one is joined and the other is discriminated. I think I'll just not use the class per hierarchy at all and use table-per-subclass even for entities with just one column in their table. Thanks for the documentation.Excrescent
Complex hierarchies do not map very well to a DB performance-wise.Wiggins
I'm learning that most data doesn't map well to RDBMSs in a variety of ways... but creativity is the screwdriver for my nail.Excrescent
E
2

joined-subclass doesn't have a discriminator because it's in a separate table. That's how it knows what the subclass is. If you want to use a discriminator you would use one table for all of your subclasses and you would use the subclass mapping

Electrocorticogram answered 24/1, 2011 at 18:0 Comment(2)
joined-subclasses can be defined in separate files; however, that's beside the point. I think you missed that the "separate table" is the root of a new inheritance hierarchy based on a discriminator. Perhaps you could provide a mapping that will do something similar to what I am puzzled about.Excrescent
@Travis, interesting re joined subclass. However, your User mapping still has to be a subclass, rather than a joined-subclass, since it's in another table.Electrocorticogram
W
2

What you want to do is not currently possible.

Check http://www.nhforge.org/doc/nh/en/index.html#inheritance for allowed constructs.

Wiggins answered 24/1, 2011 at 20:17 Comment(7)
So if I understand this right, I can't mix different inheritance strategies? Basically, if every class ultimately descends from a base-class like "Entity", then I have to pick one strategy and that's it for whole hierarchy. I understand not being able to mix at the same level, but is there any chance this will be supported for different levels in the future?Excrescent
@Travis, is there a reason you want to have a table for Entity?Electrocorticogram
Yes; there are 6 fields that are common to all my entities [Id, IsActive, DateCreated, Creator, DateModified, Modifier]. But even if I didn't need Entity, User would take its place in a similar situation if I needed to extend Contractor or Employee.Excrescent
You usually never map the "Entity" class, so that's not an issue. And no, you can't arbitrarily mix strategies beyond what's supported according to the docs. Since it's not a very common need, I doubt it will be supported unless you can provide a fully tested patch for that, which is likely to be really hard, if possible at all, to code.Wiggins
Disregarding your "never do this or that" comment (I could call Entity something else that is good base class name), the problem is isomorphic to the situation that could always occur when you have both child and grandchild descendant classes where one is joined and the other is discriminated. I think I'll just not use the class per hierarchy at all and use table-per-subclass even for entities with just one column in their table. Thanks for the documentation.Excrescent
Complex hierarchies do not map very well to a DB performance-wise.Wiggins
I'm learning that most data doesn't map well to RDBMSs in a variety of ways... but creativity is the screwdriver for my nail.Excrescent

© 2022 - 2024 — McMap. All rights reserved.