NHibernate and Generic Entities

time to read 3 min | 564 words

Colin Jack has brought up the question of generic entities, which is something that I consider fairly odd use case. Generics are very useful, but not in the final entity layer (they are very useful as layer super type, though).

First, let us understand what I am are talking about when I am thinking about generic entities:

image

The generic entity that you see is ContactInformation<TContactInfoType>, and we want to use several specialized versions of that in our application. In this case, we have contact that can be either a string or a user.

Here is an interesting tidbit, NHibernate supports this, here it the required configuration:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
				   assembly="Blog"
				   namespace="MyBlog">
	<class name="ContactInformation`1[System.String]"
		   table="ContactInformation_String">
		<id name="Id">
			<generator class="identity"/>
		</id>
		<property name="Contact" type="System.String"/>
	</class>

	<class name="ContactInformation`1[MyBlog.User]"
		 table="ContactInformation_User">
		<id name="Id">
			<generator class="identity"/>
		</id>
		<many-to-one name="Contact" class="MyBlog.User, Blog"/>
	</class>
</hibernate-mapping>

We can even do different associations to different classes, simple column for string, FK for user.

What we can't do is to map ContactInformation<TContactInfoType>, for the very simple reason that we have no way of doing it. Consider the example above, in one case, we are using a FK, in the other, a simple column. NHibernate has no way of guessing, and since I can't really think of a good reason to want to start mapping random values to my database, I think that NHibernate is doing a good thing by insisting that you tell it about how you want this mapped.

There may be a problem with querying this with HQL, but I think this can be gotten around to with importing the class name to an alias.

Now, let us get back to the diagram below, by show of hand (well, comments), how many of you think that this is a good way to design your entities?

An entity is not a list, to which you shove random data. It has a meaning in the domain, and it has a table in which you put the data, and you want to query it, etc. It would take some pretty peculiar use case to convince me that there isn't a really simplifying factor here by simply introducing SimpleContactInformation and UserContactInformation classes, which would simple derived from the generic class with the appropriate parameters. The ability to use generics is nice to cut duplicate code, but it also obstruct the clarity of the code, so I see this as significant added value.

In short, it is possible, but don't do it.