Polymorphism and identifiers

Polymorphism makes you use truly unique identifiers. If you don’t agree, consider the following scenario:
Polymorphism diagram Imagine, that client wants you to create a registry (list view, whatever), that will enable him to query assets and apply different criteria onto them (there is not much in the interface, but name can also be queried with SQL like operator). You immediately notice, that you can use polymorphic queries from NHibernate, which spans to all implementations of the given interface. They can be some problems with the queries efficiency (paging is done in the memory), but skipping this fact, you’ve done it. You have your list of assets presented to the user, who instantly notices that there are a few rows with the same id. What’s going on, you ask. Ahhh, you’re still using the old-fancy db identity identifier generator. Not only it’s generates unique id per table, but also removes all the bonuses connected with batching inserts. How can you overcome such an obstacle?
The solution is simple: use GuidGenerator, especially CombGuidGenerator, as your IIdentityGenerator. If your customer hastes these 128-bit long chains, use HiLo algorithm, which stores within the process a package of identifiers ready to be used. Once they’re used, it goes to the db to transactionally get another one. Span this HiLo for all tables/entities hierarchies which can be queried in a polymorphic way. For the best result, set it for all entities’ types, and enjoy having unique long/int identifiers across your whole database.

Polymorphic count with NHibernate

If you’re a user of NHibernate, I hope you enjoy using polymorphic queries. It’s one of the most powerful features of this ORM allowing you to write queries spanning against several hierarchies. Finally, you can even query for the derivations of object to get all the objects from db (don’t try this at home:P). The most important fact is, that having a nicely implemented dialect NH can do it in one DB call, separating specific queries by semicolon (in case of MS SQL)

// whoa!
var allObjects = session.QueryOver<object>().List();

Although the feature is powerful, you can find a small problem. How to count entities returned by the query without getting’em all to the memory. Setting a simple projection Projections.RowCount() will not work. Why? ‘Cause it’s gonna query each table with COUNT demanding at the same time that IDataReader should contain only one, unique result. It won’t happen, and all you’ll be left with it’ll be a nice exception. So, is it possible to count entities in a polymorphic way? Yes! You can define in a extension method and use it every time you need a polymorphic count.

private static int GetPolymorphicCount(ISession s, Type countedType)
    var factory = s.GetSessionImplementation().Factory;
    var implementors = factory.GetImplementors(countedType.FullName);

    return implementors
        .Select(i => s.CreateCriteria(i)
        .ToArray() // to eagerly create all the future values for counting
        .Aggregate(0, (count, v) => count + v.Value); // sum up counts

Happy counting!

NHibernate EntityAwareModelBinder for ASP MVC

It’s time to provide some more features before getting deeper into detached actions for ASP MVC. The very first requirement is to have a nice model binder, which not only uses a container to resolve all the parameter types (my previous model binder), but also is intelligent enough to deal with an ORM of your choice. And mine is NHibernate.

Before getting the final snippet, a few assumptions has to be made:

  • No hierarchies are bound automatically. For sake of simplicity, we’re considering only simple entities with no derivations.
  • All the collections, which reflect one-to-many relationships, are bound in the inverse way. The one ending has its collection marked as inversed (there is a drop-down for the many ending, where the parent can be selected)

To provide you with a better way of viewing the code, I pushed the file to the gisthub and it can be located under: https://gist.github.com/984310. It’s good time to take a look into it.

As you can see, the binder does some pretty nice things:

  • It still uses container as the fallback for all the models. Using Windsor you’d better be sure to have all of them registered
  • If entity has its id passed, it uses session to get it; otherwise a new instance is created. It’s up to you to save it in your session

Maybe it addresses a few concerns, like handling entities and non entities in one binder, but it’d be easier to get the whole idea having one straight class without the whole projects.

This is my default model binder in my current project so far and it provides strong base for the detached actions mechanism, which will be covered in the very next entry.