How do you map enums to and from the database using NHibernate? - nhibernate

Edit: Ryan raised a good point. I specifically want to be able to map to and from while still storing human-readable values in the database. That is, I don't want a bunch of enumeration integers in my database.

According to the documentation you can either leave the type attribute of the property in your mapping file blank or you define it and specify the class name of the enumeration.
Another way would be to convert the enumeration to an int and use the int as the mapped type.

You have to implement a custom IUserType. See this post.

I've never used NHibernate, but can't you just set the SQL datatype to int?

I think you can just set the type to string:
<property name="EnumProperty" Type="string" Length="50" NotNull="true" />

Related

HBM mapping image/binary

I am having trouble mapping our byte[] field. I've been looking for several solutions but none work so far. All I get is this exception:
The length of the byte[] value exceeds the length configured in the mapping/parameter.
Below is what I've got so far in the hbm.xml
<property name="Data" type="BinaryBlob">
<column name="attachmentData" sql-type="varbinary(max)"/>
</property>
Am I doing something not right here?
Update - Solution:
It turned out that I have done it incorrectly. We are inserting the byte[] via stored procedure so the property mapping has nothing to do with it. Instead, we need to tell NHibernate the type of the sprocs parameter like so:
query.SetParameter(param.Key, param.Value, NHibernateUtil.BinaryBlob);
NHibernate doesn't understand varbinary(max) and will use the default of 8000 bytes.
Therefore you will need to supply the number. I.e.
varbinary(2147483647)
I think used to work but is a regression bug.

NHibernate Property Mapping, best practise for type attribute?

I have a little doubt for mapping of property in hbm file.
Sometimes I've mapped the string field of my db in this way:
<property name="MyPropName" column="MyColumnName" length="20" />
but the same mapping can be wrote in this way:
<property name="MyPropName" column="MyColumnName" type="String(20)" />
my question is...what's the better way?
If I omit "type" attributes for property tags it works, but I don't know if there are some contraindications. Can you tell me?
And last thing...are right this associations?
db varchar fields -> type "AnsiString"
db nvarchar fields -> type "String"
The "best practice" is to only override the defaults. So, for your example, the first form would be the best.
As for the second question: yes, they are correct.
You can find all the value types and default mappings here: 5.2.2. Basic value types

NHibernate: lazy loaded properties?

NHibernate question:
Say I have a SQL table Person and it has a Picture column ( OLE Object ) . I have a class Person and it has : byte[] Picture attribute.
Is it possible to map like this ?
<property name = "Picture" column = "Picture" type = "System.Byte[]" lazy="true" />
Does the "lazy" keyword have any effect on properties or can it only be used when working with collections / bags etc?
It appears that this feature just landed in the NHibernate trunk:
http://ayende.com/Blog/archive/2010/01/27/nhibernate-new-feature-lazy-properties.aspx
I have not found any way to get this to work, but the following two ways may help you around the problem you imply:
You can map two classes for the same table, one including the byte array, the other not.
You can include a many-to-one property mapping to the same table, where the child class has the byte array included, and you then access the binary using Person.PersonPicture.Picture rather than just Person.Picture; the intermediate class can now be lazy loaded.
Neither is ideal, but they do work. Short answer - collections and many-to-one properties can be lazy loaded, straight properties not.

Custom Converters for domain types using NHibernate

My domain model is using System.Net.Uri to represent URLs, and System.Drawing.Color to represent colors. In the db, uris are simply nvarchars and colours are web (hex) rgb values.
Using NHibernate, is there some way to map between these values using some custom mapper?
I don't need to query against these items, but it would be nice if I could.
Any help is greatly appreciated.
What you need are user types. Implement IUserType or IComplexUserType (there are some more interfaces to match other needs).
There are some examples:
http://intellect.dk/post/Implementing-custom-types-in-nHibernate.aspx
http://www.lostechies.com/blogs/rhouston/archive/2008/03/23/mapping-strings-to-booleans-using-nhibernate-s-iusertype.aspx
Using the user type, you can map any class to any number of columns of any type. Implementing the user type means implementing the mapping between them.
The mapping could look like this:
<property "MyColor" type="ColorUserType">
<column name="R"/>
<column name="G"/>
<column name="B"/>
</property>
You could use Transformers. I used them for a native query which transforms the result to a custom object. In your case you could adjust the get properties to transform to your Uri and Color representation.

NHibernate - is there any point in setting length attribute for properties/columns?

typically definition of property/column looks like this:
<property name="DocumentSummary" column="DocumentSummary" length="100" type="String">
<column name="DocumentSummary" />
</property>
I was assuming that NHibernate will validate data using length attribute before inserting/updating a row. Unfortunately it seems to be invalid assumption. So question is if NHibernate is using length attribute for anything? Does it make sense to set it for each property?
It using it to create database definition sql. Look at SchemaExport class.
Also you might be able to programmically pull the lengths from the mappings, see this question. Note that that is for Java Hibernate, but I believe you might be able to translate that to NHibernate.
Yes, setting the Length property makes a different where you have string columns with a length that exceeds the default maximum length.
We have a column of type NVARCHAR(MAX). If we didn't set the length property, NHibernate would fail to set the string value if the value had a length greater than 4096 characters.
(This example uses Mapping-By-Code, because we're in 2017 :-)
classMapper.Property(
tickerFeed => tickerFeed.StaticTickerText,
propertyMapper =>
{
propertyMapper.Column("StaticTickerText");
propertyMapper.Length(int.MaxValue);
}
);
However, we found we could achieve the same result using IPropertyMapper.Type to stipulate that it was a large string.
classMapper.Property(
tickerFeed => tickerFeed.StaticTickerText,
propertyMapper =>
{
propertyMapper.Column("StaticTickerText");
propertyMapper.Type(NHibernateUtil.StringClob);
}
);
We ended up going with the propertyMapper.Type option, as it is more explicit.