NHibernating with interfaces as entities, pt. 2

The solution to the question, what can go wrong with NHibernate, when you use interfaces as your entities mapped with NH is… naming.

When you try to save a transient object, to make it persistent with NH, you call ISession.Save(object) method. If you drilled down its implementation you’d see that it fires NH’s event SaveOrUpdateEvent which finally, after calling the default event handler for this event, would try to get the persister of the entity being saved. What for? Because you’ve got to know how you are trying to make persistent and later, saved in a db.

Let’s take a look at the implementation provided with a SessionImpl.GetEntityPersister method. At the very first lines of code, the method calls another session’s method called GuessEntityName. Guessing method firstly delegates the question to the interceptor, and if one was kind enough to help it to deal with it, it returns the result of the interceptor’s call. Otherwise… GetType of the entity method is called! If the result of resolving entity’s interface from container was wrapped with a proxy, some proxy type will be returned (in DynamicProxy it will be nicely placed in a dynamic assebly with a cute namespace) and because it is not what was mapped, an error will occur!

The only solution is to traverse all interfaces implemented by the object and find the one you’ve written in your mappings in the interceptor method. You can do it simply with the code presented below, initializing the finder with all interfaces of all your entities. Remember to do not cross trees in a forest of your interface-entity derivations:P

/// <summary>
/// The interface finder allows you to find the deepest interface from a specified set of interfaces.
/// </summary>
/// <remarks>
/// The interfaces inheritance graph should be a forest.
/// </remarks>
public class InterfaceFinder : IDisposable
{
	private readonly List<Type> _interfaces;
	private readonly Dictionary<Type, int> _interfaceToLevel;
	private readonly Dictionary<Type, Type> _cacheObjectTypeToInterface;
	private readonly ReaderWriterLockSlim _rwl;

	public InterfaceFinder(IEnumerable<Type> interfaces)
	{
		if (!interfaces.Any())
		{
			throw new ArgumentException("No interfaces passed", "interfaces");
		}

		_interfaces = interfaces.ToList();
		_interfaceToLevel = new Dictionary<Type, int>();
		_cacheObjectTypeToInterface = new Dictionary<Type, Type>();

		// prepare dictionary counting ancestors
		foreach (var i in interfaces)
		{
			if (!i.IsInterface)
			{
				throw new ArgumentException(string.Format("The type {0} is not an interface", i.FullName));
			}

			var ancestorCount = i.GetInterfaces().Count(t => interfaces.Contains(t));
			_interfaceToLevel[i] = ancestorCount;
		}

		// create only when fully initialized
		_rwl = new ReaderWriterLockSlim();
	}

	/// <summary>
	/// Gets the depest interface from inheritance trees retrieved from
	/// the constructor parameter.
	/// </summary>
	/// <param name="o">The object to be searched for interfaces.</param>
	/// <returns>The deepest interface of a hierachy found in the object interfaces.</returns>
	public Type GetDeepestInterface(object o)
	{
		o.ThrowIfNull("o");

		var type = o.GetType();

		// enter read lock, try found, multiple threads can enter
		_rwl.EnterReadLock();
		try
		{
			Type result;
			if (_cacheObjectTypeToInterface.TryGetValue(type, out result))
			{
				return result;
			}
		}
		finally
		{
			_rwl.ExitReadLock();
		}

		// write lock, cause no entry found, one thread can enter
		_rwl.EnterWriteLock();
		try
		{
			Type result;
			if (_cacheObjectTypeToInterface.TryGetValue(type, out result))
			{
				return result;
			}

			result = GetDeepestInterface(type);
			_cacheObjectTypeToInterface[type] = result;
			return result;
		}
		finally
		{
			_rwl.ExitWriteLock();
		}
	}

	private Type GetDeepestInterface(Type objType)
	{
		var interfaces = objType.GetInterfaces().Intersect(_interfaces);

		var levels = interfaces.Select(t => _interfaceToLevel[t]).ToArray();
		var countDistinct = levels.Distinct().Count();

		if (countDistinct != levels.Length)
		{
			throw new InvalidOperationException(
				"The type of passed object implements to many interfaces, " +
			"disallowing to find one path in derivation tree. The found implemented interfaces are: " +
			string.Join(", ", interfaces.Select(i => i.FullName).ToArray()));
		}

		// find the interface with the biggest depth
		return interfaces.OrderByDescending(t => _interfaceToLevel[t]).First();
	}

	public void Dispose()
	{
		_rwl.Dispose();
	}
}

Tests not included :P

NHibernating with interfaces as entities, pt. 1

No catchy title this time:P
Have you ever considered using interfaces as entities in your application with NH as ORM? If not, and you never considered this option I can share a few thoughts about it with you.

Proxifing an interface is easier than proxifing a class, especially when using a tool like DynamicProxy which as far as I know still does not has this ability (yep, I’ve read about it on Kozmic’s blog). Why on earth proxify each entity you may ask? During the last project I was involved in, my colleague wanted to ensure, that setting properties and calling methods of one entity can be done only in explicitly set up scopes (explicit security). It’s quite easy when you can intercept all the setters and other, non-property method calls. All you’ve got to do is during instantiation of an entity wrap it with a certain proxy. What about instantiating entities’ implementations? There should be some, because it very unpleasant to have your entities only data oriented with no methods at all. This can be easily done with your implementation of NH’s IInterceptor. There is an interceptor method Instantiate(string entityName, EntityMode entityMode, object id); which, with help of your favorite container, can be turned into a entity factory. The code would look like this:

public override object Instantiate(string clazz, EntityMode entityMode, object id)
{
	if (entityMode == EntityMode.Poco)
	{
		var metadata = _sessionFactory.GetAllClassMetadata()[clazz];
		var type = metadata.GetMappedClass(entityMode);

		if (type != null)
		{
			var instance = _unityContainer.Resolve(type);
			var classMetadata = _sessionFactory.GetClassMetadata(clazz);

			classMetadata.SetIdentifier(instance, id, entityMode);

			return instance;
		}
	}

	return null;
}

The session can easily create the entity to hydrate it, we can be given our ISomeEntity with Load, Get, List. What about creating your entity for the first time? It can be also achieved providing an interface of IEntityFactory implemented with usage of the very same container used in the interceptor.
So far so good. But is there a catch? Yes there is and it’ll be revealed soon :)

ASP MVC Model binders

Recently I had to create a model for ASP MVC, which would be bound by the model binder and had its properties set according to the request. It’s the most common case you can imagine, but there was one ‘but’. The model, because of its nature had to have non-default constructor. It was only a few parameters but it broke the DefaultModelBinder, which simply couldn’t find all the needed values. My response was quite fast, specially having the controller factory implemented in the following way:

/// <summary>
/// The controller factory building up the controllers with the unity container.
/// </summary>
public class ControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer _container;

    public ControllerFactory(IUnityContainer container)
    {
        _container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, 
        Type controllerType)
    {
        return (IController)_container.Resolve(controllerType, null);
    }
}

The very next step was to replace the default binder stored in ModelBinders.Binders.DefaultBinder with another, controller-based implementation:

/// <summary>
/// The model binder building up the model objects with the unity container.
/// </summary>
public class ModelBinder : DefaultModelBinder
{
    private readonly IUnityContainer _container;

    public ModelBinder(IUnityContainer container)
    {
        _container = container;
    }

    protected override object CreateModel(ControllerContext controllerContext, 
                                          ModelBindingContext bindingContext,
                                          Type modelType)
    {
        var type = modelType;
        if (modelType.IsGenericType)
        {
            var genericTypeDefinition = modelType.GetGenericTypeDefinition();
            if (genericTypeDefinition == typeof (IDictionary<,>))
            {
                type = typeof (Dictionary<,>).MakeGenericType(modelType.GetGenericArguments());
            }
            else if (((genericTypeDefinition == typeof (IEnumerable<>)) ||
                      (genericTypeDefinition == typeof (ICollection<>))) ||
                     (genericTypeDefinition == typeof (IList<>)))
            {
                type = typeof (List<>).MakeGenericType(modelType.GetGenericArguments());
            }
        }

        // in the base method: return Activator.CreateInstance(type);
        return _container.Resolve(type, null); 
    }
}

As you can compare, the method simply delegates creating model to the container. Having this binder set allowed passing models with non-default constructors, so the problem was solved:] After a while, I considered following case: if the type is constructed with a container, the controller can also be passed an object implementing an interface registered in container. Hence, if a method needs a NHibernate ISession, this can be expressed not only as a parameter in Controller constructor, but also as a method parameter. This paradigm creates controllers with no parameters needed in constructor (or only common parameters, used in all actions) and all the others passed as action parameters. The result is a method, which can be perfectly tested in an environment where the only smallest, needed set of dependencies is passed (no more constructors with not needed in the current method parameters). What do you think about it?

An example of a controller:

public class CarController : Controller
{
    private readonly ISession _session;
    private const int PageSize = 10;

    public HomeController(ISession session)
    {
        _session = session;
    }

    public ActionResult Rent(IUserService userService, Guid carId)
    {
        using (var tx = _session.BeginTransaction())
        {
            var car = _session.Load<Car>(carId);
            var user = userService.GetCurrentUser();

            car.RentBy(user);
            
            tx.Commit();
        }

        return View();
    }

    public ActionResult Index( int? pageNo)
    {
        var page = pageNo ?? 0;

        var cars = _session.CreateQuery("from Car")
            .SetFirstResult(page*PageSize)
            .SetMaxResults(PageSize)
            .Future<Car>();

        return View(cars);
    }
}