Page 1 of 2

problem with discriminator columns

Posted: Thu 19 Jan 2012 19:13
by mindplay
I'm trying to use table-per-hierarchy strategy to map a number of subclasses, and I'm trying to use an int column for the discriminator.

Here's a screenshot of my relationship settings.

This results in the following generated mapping:

Code: Select all

    
      
    
Which results in an exception like "Could not format discriminator value to SQL string of entity MyApp.Entities.LogEntry".

My discriminator values are simple numeric values like "1000", "1001", etc. - but it turns out the opposite end of each inheritance has it's own Type and Column.Type specifications, and those were set to the default, "string" type!

How come I'm allowed to have mismatching discriminator types?

It seems like, if you change a base discriminator type, this ought to propagate to all derived discriminator types?

Or at least, the "validate" function on the model should report these as errors?

Also, base-classes must have a discriminator value, unless they're configured as Abstract=True - this could be added to validation as well.

Posted: Tue 24 Jan 2012 10:11
by Shalex
Thank you for your suggestions. We will notify you about the results of our investigation.

Posted: Thu 26 Jan 2012 16:45
by Shalex
mindplay wrote:"Could not format discriminator value to SQL string of entity MyApp.Entities.LogEntry"
The reason of this error is that you have not set the Base Class Discriminator Value property which has to be specified explicitly. If Base Class Discriminator Value is not set, NHibernate runtime tries to calculate Discriminator's Type basing on the name of the class (string) but the discriminator type in this case is int. We hope this strange behaviour of NHibernate runtime will be fixed in the next versions of NHibernate.
mindplay wrote:How come I'm allowed to have mismatching discriminator types?
This is not the reason of the error (see above). The Discriminator property doesn't make sense in the derived classes (it is not used). We will hide it in the next build of Entity Developer.
mindplay wrote:Also, base-classes must have a discriminator value, unless they're configured as Abstract=True - this could be added to validation as well.
It doesn't matter whether a base class is abstract or not. We have added the following warnings:
1) "Discriminator Value is not set in Base Class"
2) "Discriminator Value is not set in Derived Class"

Posted: Thu 26 Jan 2012 17:45
by mindplay
Thank you, I learned most of that the hard way over the last couple of days ;-)

I guess I assumed NH would not require a discriminator-value for an abstract derived class - it does require that, even though it's complete pointless and will never be used. It's not like you can even create an instance of an abstract type, and thus you will certainly never need to save an instance of an abstract type... odd...

Posted: Fri 10 Feb 2012 12:08
by Shalex
New build of Entity Developer 4.2.129 is available for download now!
It can be downloaded from http://www.devart.com/entitydeveloper/download.html (trial version) or from Registered Users' Area (for users with active subscription only).
For more information, please refer to http://www.devart.com/forums/viewtopic.php?t=23375 .

Posted: Fri 10 Feb 2012 17:19
by mindplay
I believe this is in fact incorrect, and does work as you would expect in NH - I did not have discriminator-values defined in my HBML files for abstract types, and I do not believe this is required.

The validator now complains about this for abstract types - I believe this behavior is incorrect.

For now, I'm adding dummy discriminator-values to my abstract base-classes - but having to come up with useless discriminator-values and having them appear in the mapping-files, seems unnecessary.

Posted: Fri 10 Feb 2012 19:19
by mindplay
Just to confirm, I have verified that this behavior is incorrect - ED should not report missing discriminator as an error when the class is abstract.

I checked, and mappings do work correctly with abstract="true" and no discriminator, as it should.

Posted: Wed 15 Feb 2012 12:58
by Shalex
Thank you for your report. We are investigating the issue.

Posted: Fri 17 Feb 2012 17:41
by Shalex
The bug with displaying warning when Discriminator Value is not set for abstract classes is fixed. We will post here when the corresponding build of Entity Developer is available for download.

Posted: Mon 27 Feb 2012 13:46
by Shalex
New build of Entity Developer 4.2.138 is available for download now!
It can be downloaded from http://www.devart.com/entitydeveloper/download.html (trial version) or from Registered Users' Area (for users with active subscription only).
For more information, please refer to http://www.devart.com/forums/viewtopic.php?t=23476 .

Posted: Mon 27 Feb 2012 15:37
by mindplay
It still doesn't work.

For multiple levels of inheritace, e.g.: A extends B extends C, B and C are abstract, it gives an error-message for the inheritance association itself:

"Derived Class Discriminator Value is not specified."

Posted: Tue 28 Feb 2012 16:42
by mindplay
The mapping generated for an abstract base-class with no discriminator also does not work:

Code: Select all

  
<class name="MyApp.Entities.Task, MyApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" table="Task" abstract="true"> 
If you're using a discriminator-type other than String, simply leaving off the discriminator-value attribute will result in an NH error when that mapping is loaded.

When the discriminator-value attribute is absent, NH defaults to a discriminator-value equivalent to the class-name, in this case "Task" - and in turn, tries to convert this to another type (such as Int32) and raises an error.

The correct mapping looks like this:

Code: Select all

  
<class name="MyApp.Entities.Task, MyApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" table="Task" discriminator-value="not null" abstract="true"> 
The special discriminator-value "not null" is recognized by NH and works for mapping things like abstract classes and interfaces.

Posted: Sat 03 Mar 2012 14:19
by Shalex
mindplay wrote:For multiple levels of inheritace, e.g.: A extends B extends C, B and C are abstract, it gives an error-message for the inheritance association itself...
We will change behaviour: the "Invalid inheritance 'C_B'. Derived Class Discriminator Value is not specified." message will not be displayed in this case because both C and B are abstract.
mindplay wrote:Just to confirm, I have verified that this behavior is incorrect - ED should not report missing discriminator as an error when the class is abstract.

I checked, and mappings do work correctly with abstract="true" and no discriminator, as it should.
mindplay wrote:The mapping generated for an abstract base-class with no discriminator also does not work...
1. We have removed warning about missing discriminator-value for the abstract base-class because you have asked us about this.
2. Value of discriminator-value has to be set by user manually. Otherwise, it defaults to the class name.

Posted: Mon 05 Mar 2012 13:49
by mindplay
Shalex wrote:2. Value of discriminator-value has to be set by user manually. Otherwise, it defaults to the class name.
I thought that's what I just explained above?

That's what the special "not null" value is for - it is required to generate a working abstract mapping. Without it, your abstract mappings do not work.

Posted: Tue 06 Mar 2012 15:06
by Shalex
We consider that setting discriminator-value (null, not null, etc) implicitly is incorrect behaviour. This value should be specified by a user explicitly basing on the approach he is going to implement.

Assuming that there will be no default discriminator-value, would you like us to return the old behaviour when the "Discriminator Value is not set in Base Class" warning is generated for the abstract class as well?