Page 1 of 2

Mapping enum with NH

Posted: Tue 13 Dec 2011 23:09
by mindplay
I added an Enum type, added a property and chose the enum type from the type drop-down.

I get the following exception:

NHibernate.MappingException: Could not determine type for: Ongweoweh.Entities.TaskType, Ongweoweh, for columns: NHibernate.Mapping.Column(Type)

It doesn't work, and I don't understand how this was intended to work.

Looking at the generated HBM, it simply has the type-name in the generated attribute, which seems wrong - the type-name in the attribute is supposed to be the name of an NH type "handler", a type that can convert back/forth between a .NET enum type and a column type (typically int, but string is also supported with the EnumStringType class:

http://elliottjorgensen.com/nhibernate- ... gType.html

Simply putting the name of an enum in the attribute does not work - and should not, as far as my understanding of NH goes...

What gives?

Posted: Thu 15 Dec 2011 14:13
by Shalex
The following DataModel1.Class1.hbm.xml was generated after adding to the model (in design time) enum Enum1:int{Member1, Member2} and class Class1{int Property1; Enum1 Property2}:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="ConsoleApplication492" namespace="ConsoleApplication492" xmlns="urn:nhibernate-mapping-2.2">
  <class name="Class1" table="Class1s" schema="dbo">
    <id name="Property1" type="Int32">
      <column name="Property1" not-null="true" precision="10" scale="0" sql-type="int" />
      <generator class="assigned" />
    </id>
    <property name="Property2" type="Enum1">
      <column name="Property2" precision="10" scale="0" sql-type="int" />
    </property>
  </class>
</hibernate-mapping>
The run-time works OK. Could you please point out the problem?

Posted: Thu 15 Dec 2011 15:16
by mindplay
I get the same exception every time, even with a simple example like yours - in this case, I added a class Foo { public Id; public BarType Bar } and an enum BarType { A=1, B=2, C=3 } both via the visual designer - I still get a similar exception:

NHibernate.MappingException: Could not determine type for: MyApp.Entities.BarType, MyApp, for columns: NHibernate.Mapping.Column(Bar)

Can you explain why this should work? Looking at the generated XML, I don't see why or how this is expected to work:

Code: Select all

<property name="Bar" type="BarType">
      <column name="Bar" />
    </property> 
type="BarType" implies that there's an NH type called "BarType", but that's just the name of the enum type I defined - what NH needs, is the name of a type that convert between BarType and the "int" SQL-type.

Did you write/configure such a type elsewhere?

Or how come this works for you?

Posted: Thu 15 Dec 2011 16:05
by mindplay
Okay, a bit more info.

According to the documentation you have two options for enums.

Leave out the type entirely, and let NH guess the type by using reflection:

Code: Select all

<property name="Bar">
      <column name="Bar" />
    </property>     
This works for me.

Or specify the fully qualified type-name of the enum:

Code: Select all

<property name="Bar" type="MyApp.Lib.BarType, Ongweoweh">
      <column name="Bar" />
    </property>   
This also works for me.

Simply putting an unqualified type-name in the type-attribute, from what I could read, causes NH to look for an NH type of that name - it will not "guess" that you're referring to a .NET type.

But either way, it seems like there should be an option to specify the NH type for a property in ED? So that you can choose what NH-type you want to use. So that, for example, you could use either the TrueFalse or YesNo NH-types for a Boolean property, or a custom type when you need to map an enum-type to a string-column.

Posted: Thu 15 Dec 2011 19:51
by mindplay
Is there any way to override the output type-attribute by editing the template? This would enable me to implement a custom property with an NH type override.

Posted: Mon 19 Dec 2011 15:22
by mindplay
To anybody else experiencing this problem, here's a work-around:

When specifying the property-type on the diagram, type in the fully qualified name of the enum-type.

If you pick it from the drop-down, it will not be qualified, neither in the generated code or in the mapping.

Entering the fully qualified name results in some verbosity in the generated code - since the fully qualified name will show up both the code and mapping files, but it works.

Posted: Mon 19 Dec 2011 20:10
by mindplay
Yikes, this work-around is only good if your enum-types are in a different namespace - unfortunately, after saving/loading the model, ED "optimizes" the fully qualified name away, probably because it's technically redundant.

For now, I'm going to put my enum-types in a different namespace, and define them by hand, rather than defining enums in the model...

Posted: Tue 20 Dec 2011 11:06
by Shalex
As we understood, you are using external enums (not from your model), aren't you? But, for some reason, you are creating enum in your model which is intermediate between external enum and the data type of your property in a class. In this case, remove your intermediate enum from the model and assign the type of your property directly to the external enum: double click on the property in the designer and set the full name of your external enum.

If this doesn't help, please send us a small test project so that we can reproduce the issue in our environment.

Posted: Tue 20 Dec 2011 13:51
by mindplay
Shalex wrote:As we understood, you are using external enums (not from your model), aren't you?
No. I have tried both using purely an enum defined in ED, and an enum defined in my own codebase. Neither works, unless I put the fully qualified type-name into ED - in which case, both works equally well; my own type, or one generated by ED. (the enum types I wrote by hand are identical to the ones generated by ED anyhow...)
Shalex wrote:But, for some reason, you are creating enum in your model which is intermediate between external enum and the data type of your property in a class. In this case, remove your intermediate enum from the model and assign the type of your property directly to the external enum: double click on the property in the designer and set the full name of your external enum.
I'm not sure what you mean by intermediate? As far as I know, it's not possible to extend enums.

I'm not doing anything weird here, as far as I know - if I create an empty project with a Foo class, BarType enum and a Foo.Bar property of that type, the generated mapping will read type="BarType" on the property mapping - and it doesn't work.

If I correct the type-name in ED to "MyApp.Entities.BarType", thus forcing ED to write this fully qualified name into the type-attribute, it works.

If it happens to work in your NH setup without qualifying the type, I don't know how it would - according to NH documentation, it's not correct, neither is it very performant, as NH has to search for the type.

I would recommend you write out the full type-name in the mapping files - according to documentation, that is the safest and most performant approach.

Posted: Fri 23 Dec 2011 09:04
by Shalex
We will investigate the issue with setting full type-name of enums and post here about the results.

Posted: Fri 23 Dec 2011 09:52
by Shalex
The bug with setting full enum name in property type is fixed. We will post here when the corresponding build of Entity Developer is available for download.

Posted: Thu 12 Jan 2012 16:36
by Shalex
New build of Entity Developer 4.2.110 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 valid subscription only).
For more information, please refer to http://www.devart.com/forums/viewtopic.php?t=23135 .

Re: Mapping enum with NH

Posted: Fri 09 Aug 2013 09:34
by PeterM
Hi, sorry to dig up this old issue. However I think this problem was reintroduced in a newer version of Entity Developer as I'm running into the same problem described here and when using the custom type where I define the full name (including the assembly) it works correctly.
As far as I can see the fluent mapping is created correctly, but the xml mapping is missing the assembly.

Re: Mapping enum with NH

Posted: Wed 14 Aug 2013 16:28
by Shalex
We cannot reproduce the problem with the latest (5.5.164) build of Entity Developer.

The names of assembly and namespace can be set in the following ways:
1) using the "MyNamespace.MyEnum, MyAssembly" format in the Type field of the class property
2) via Assembly and Namespace properties of the enum
3) via Default Assembly and Default Namespace properties of the model

Please specify the exact (x.xx.xxx) build of your Entity Developer and send us a small test project to reproduce incorrect generation of XML mapping. Are you using a predefined NHibernate template?

Re: Mapping enum with NH

Posted: Fri 16 Aug 2013 10:21
by PeterM
When setting the Assembly property of the Enum itself it indeed works as expected, when leaving it empty it doesn't use the Default Assembly of the model.
I'm using that exact last build. I've send a model which includes two enums, one with the Assembly defined and one without (where I am assuming the default should be used?!).