How do I map nested generics in NHibernate - nhibernate

In NHibernate you can map generics like this
<class name="Units.Parameter`1[System.Int32], Units" table="parameter_int" >
</class>
But how can I map a class like this?
Set<T> where T is a Parameter<int> like this Set<Parameter<int>>
My mapping hbm.xml looking like this fails
<class name="Set`1[[Units.Parameter`1[System.Int32], Units]],Units" table="settable"/>
I simplified my mappings a little to get my point accross very clearly. Basically I want NHibernate to map generic class which has has generic type parameter.
Want I understand from googling around is that NHibernate is not able to parse the name to the correct type in TypeNameParser.Parse() which result in the following error when adding the mapping to the configuration
System.ArgumentException: Exception of type 'System.ArgumentException' was thrown.
Parameter name: typeName#31
Anybody found a way around this limitation?

I think you'll have to map it as a custom type. See this article and google for IUserType.

Related

Determine the type of a dynamic model

In NHibernate, you can map tables but without writing a class for them -- "dynamic models". These are returned as Hashtable instances.
If you connect an event listener, for example an IPreDeleteEventListener, you can receive PreDeleteEvents. These have:
object[] DeletedState
object Entity
object Id
IEntityPersister Persister
IEventSource Session
I see no way here to get the type of the object. Specifically, I want the entity-name of the <nh:class> (but table would be great, too).
It seems like there ought to be a way to get this, but I'm just not seeing it. I'm being told that an event fired on an entity, and being handed a Hashtable and Id but I can't figure out what type it is.
Is there some method I'm just missing? Or can anyone think of a usable workaround?
You can get the entity-name using the $type$ key on the dictionary/hashtable itself.
To get more granular details like table name, you'd probably have to find those in the runtime NHibernate configuration (looking up by the entity-name value).

NHibernate: projecting a subclass type of an entity

How do I query a class of a specific entity in NHibernate?
I basically want a projection that returns a System.Type of each row that matches criteria.
I have looked at Get subclass type from projection with NHibernate however when I create Projections.Property("alias.class") or Projections.Property("class"), I always get could not resolve property 'class'.
Projections.Property("class") is possible and it works, but only if the class has a discriminator.
I got an answer from person on my team (Denis Bykov).
Unfortunately I had hard time making him answer here so I can award him reputation.
I don't think this is possible using NHibernate directly; but consider adding the following to your base entity class (assuming you have one):
protected virtual Type GetTypeUnproxied() {
return GetType();
}
After you have queried your entities, you can interrogate this property to return the actual CLR type of the entity.
If you can't get access to the type through NHibernate for projection purposes, perhaps you can store the System.Type in a field using a custom user type. This should give you the exact functionality you require.

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.

Is there a way to define reusable properties to n-hibernate mappings?

I have a scenario that i want to add some standard properties to my entities. Meaning that i will have e.g. 1 int and 2 string properties applied to all relevant entities. I have over 100 mapping files and most but not all will be hosts to these new properties. In the classes its easy to define this; in the mappings however i've found no reference other than creating a utility or xslt and applying that (How to define reusable <generator> elements in hibernate mapping).
However i want to be able to add/modify/remove properties from this "standard" mapping.
thx for any replies
Edit1: an example of the mapping i want to add
<property name="TimeOfEdit" column="TimeOfEdit" type="DateTime" not-null="true"/>
<many-to-one name="EditedBy" column="FK_EditedBy" cascade="save-update" not-null="true" />
Edit2:
I removed the accepted solution because with NH 2.1.1 XML Entities are not working (NH-1236) and NH will throw a "DTD is prohibited in this XML document"
It depends on how these properties are implemented in your classes.
If they are all defined in a base class or interface, you could map them once in the base class or interface, and derive using union-subclass. There are some limitations. Read this chapter in the NHibernate documentation about it.
If you decide to put them together into a class, you could map them as a user type. This will be similar to a component, but you could specify some things like type names, lengths and others in the user type. You still need to specify each column name.
There is another option: you could use XML entities. This is a rather primitive feature from XML which is supported by NHibernate. Read this chapter in the NH reference documentation where it is mentioned.
Creating a special code generator for your specific case is your only option.
Option 1:
-Define these 3 properties in a base class
-have your entities inherit from this base
-set up 'table per class hierarchy'
Option 2:
-Define these 3 properties as a component.
-You can have the mapping for these 3 properties in one file that is reused.
You might take a look at fluentNHibernate, It will simplify the mapping work for you. With With auto mapping you may only need an abstract base class to define these properties.
It seems that the only to do this, is to use Dynamic Mapping (http://ayende.com/Blog/archive/2008/05/01/Dynamic-Mapping-with-NHibernate.aspx)
as such since i've already defined an interface that my entities will use for the new properties (lets say IAuditable) its just a matter of running the appropriate code at the NH-session initialization
Configuration cfg = new Configuration() Mappings mappings = cfg.CreateMappings();
foreach (var persistentClass in mappings.Classes)
{
if (persistentClass.MappedClass is IAuditable)
{
...
}
}
and then
cfg.BuildSessionFactory();
to have it wired up and ready to be used
for about 85 classes the performance impact is negligible

How do you map enums to and from the database using 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" />