Try fast search NHibernate

26 October 2008

entity-name in action: Entity Abstraction

Another time I start from :

“Program to an interface and not to an implementation”

I want have the same approach, I’m using for DAOs, Models, Presenters, Validation, and so on, for my domain.

The domain:

public interface IEntity<TIdentity>: IEquatable<IEntity<TIdentity>>
{
TIdentity Id { get; }
}

public interface IAnimal : IEntity<int>
{
string Description { get; set; }
}

public interface IReptile : IAnimal
{
float BodyTemperature { get; set; }
}

public interface IHuman : IAnimal
{
string Name { get; set; }
string NickName { get; set; }
DateTime Birthdate { get; set; }
}

public interface IFamily<T> : IEntity<int> where T : IAnimal
{
T Father { get; set; }
T Mother { get; set; }
ISet<T> Childs { get; set; }
}

Because I’m going to work with interfaces I will need a sort of factory to have transient-instances of my entities. For this example I’m going to use something simple and more “general purpose”; a class resolver:

public interface IClassResolver : IDisposable
{
T Resolve<T>() where T : class;
T Resolve<T>(string service) where T : class;
}

The responsibility of the IClassResolver implementor is return an instance for a given Type where the Type is an interface (well… in general is an interface). The concrete implementation of a IClassResolver will be injected using some IoC framework but for this post I will use a simple static exposer:

public class DI
{
private static IClassResolver resolver;
private DI() {}

public static IClassResolver Resolver
{
get
{
if (resolver == null)
{
throw new InvalidOperationException("Resolver was not initialized. Use StackResolver.");
}

return resolver;
}
}

public static void StackResolver(IClassResolver dependencyResolver)
{
resolver = dependencyResolver;
}
}

As you can see nothing so complicated.

Now I have all needed to write a test for my domain:

[Test]
public void DomainAbstraction()
{
using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var rf = DI.Resolver.Resolve<IReptile>();
rf.Description = "Crocodile";

var rm = DI.Resolver.Resolve<IReptile>();
rm.Description = "Crocodile";

var rc1 = DI.Resolver.Resolve<IReptile>();
rc1.Description = "Crocodile";

var rc2 = DI.Resolver.Resolve<IReptile>();
rc2.Description = "Crocodile";

var rfamily = DI.Resolver.Resolve<IFamily<IReptile>>();
rfamily.Father = rf;
rfamily.Mother = rm;
rfamily.Childs = new HashedSet<IReptile> { rc1, rc2 };

s.Save(rfamily);
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var hf = DI.Resolver.Resolve<IHuman>();
hf.Description = "Flinstone";
hf.Name = "Fred";

var hm = DI.Resolver.Resolve<IHuman>();
hm.Description = "Flinstone";
hm.Name = "Wilma";

var hc1 = DI.Resolver.Resolve<IHuman>();
hc1.Description = "Flinstone";
hc1.Name = "Pebbles";

var hfamily = DI.Resolver.Resolve<IFamily<IHuman>>();
hfamily.Father = hf;
hfamily.Mother = hm;
hfamily.Childs = new HashedSet<IHuman> { hc1 };

s.Save(hfamily);
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var hf = s.CreateQuery("from HumanFamily").List<IFamily<IHuman>>();

Assert.That(hf.Count, Is.EqualTo(1));
Assert.That(hf[0].Father.Name, Is.EqualTo("Fred"));
Assert.That(hf[0].Mother.Name, Is.EqualTo("Wilma"));
Assert.That(hf[0].Childs.Count, Is.EqualTo(1));

var rf = s.CreateQuery("from ReptilesFamily").List<IFamily<IReptile>>();

Assert.That(rf.Count, Is.EqualTo(1));
Assert.That(rf[0].Childs.Count, Is.EqualTo(2));

tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
s.Delete("from HumanFamily");
s.Delete("from ReptilesFamily");
tx.Commit();
}
}

Note: s.Save(hfamily) <<=== there isn’t a string for the entity-name; now NH are supporting it.

As you can see the users of my domain (the test in this case), are working only using interfaces; there isn’t a reference to a concrete implementation of my domain. The concrete implementation of the domain is trivial and you can see it downloading the code. The main thing you will notice, in the implementation, is the absence of the virtual modifier.

Wiring…

To wire the interface, with its concrete implementation, I want use NHibernate. The mapping is similar to the previous:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="EntityNameInAction.Abstraction.Entities.Impl"
namespace="EntityNameInAction.Abstraction.Entities.Impl.Naturalness"
default-access="backfield">

<
class name="MyAnimal" abstract="true"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IAnimal, EntityNameInAction.Abstraction.Entities"
entity-name="Animal">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="kind"/>
<
property name="Description"/>
</
class>

<
subclass name="MyHuman"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities"
extends="Animal"
entity-name="Human">
<
property name="Name"/>
<
property name="NickName"/>
<
property name="Birthdate" type="Date"/>
</
subclass>

<
subclass name="MyReptile"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities"
extends="Animal"
entity-name="Reptile">
<
property name="BodyTemperature"/>
</
subclass>

<
class name="MyFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities]]"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities]], EntityNameInAction.Abstraction.Entities"
table="Families" discriminator-value="Reptile" where="familyKind = 'Reptile'"
entity-name="ReptilesFamily">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" cascade="all" entity-name="Reptile"/>
<
many-to-one name="Mother" cascade="all" entity-name="Reptile"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId" />
<
one-to-many entity-name="Reptile"/>
</
set>
</
class>

<
class name="MyFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities]]"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities]], EntityNameInAction.Abstraction.Entities"
table="Families" discriminator-value="Human" where="familyKind = 'Human'"
entity-name="HumanFamily">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" cascade="all" entity-name="Human"/>
<
many-to-one name="Mother" cascade="all" entity-name="Human"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId" />
<
one-to-many entity-name="Human"/>
</
set>
</
class>
</
hibernate-mapping>

Mapping highlight


  • class/subclass name: are my concrete classes (implementors of domain)
  • proxy : is the interface (the domain); using it as proxy I can avoid virtual methods in the implementation because the underlining Dynamic-Proxy will inherit from the interface. Using interface I have many others vantages but is to long explain each (only one for example: I can cast a proxy-instance to an interface)
  • entity-name :  is the name I will use for persistence and represent another abstraction-level. For persistence stuff I can use a “conceptual-name” of the entity without take care about its representation in C#. As you can see the entity-name are playing on each association/aggregation/extends; not the concrete class nor the interface.
  • As in this post the domain is represented in two tables.

Class Resolver

In the implementation of IClassResolver I’m going to use the NHibernate’s mapping to wire the interface of the domain (ex: IHuman) to its concrete class (ex: MyHuman) trough the entity-name. Is it not clear ? ok perhaps the code will be more clear

public class NhEntityClassResolver : IClassResolver
{
private readonly Dictionary<Type, string> serviceToEntityName = new Dictionary<Type, string>();
public NhEntityClassResolver(ISessionFactoryImplementor factory)
{
if(factory == null)
{
throw new ArgumentNullException("factory");
}
Factory = factory;
InitializeTypedPersisters();
}

private void InitializeTypedPersisters()
{
foreach (var entityName in Factory.GetAllClassMetadata().Keys)
{
serviceToEntityName
.Add(Factory.GetEntityPersister(entityName)
.GetConcreteProxyClass(EntityMode.Poco), entityName);
}
}

public ISessionFactoryImplementor Factory { get; private set; }

#region Implementation of IDisposable

public void Dispose()
{
}

#endregion

#region
Implementation of IClassResolver

public T Resolve<T>() where T : class
{
string entityName;
if(serviceToEntityName.TryGetValue(typeof(T), out entityName))
{
return Resolve<T>(entityName);
}
return null;
}

public T Resolve<T>(string service) where T: class
{
return Factory.GetEntityPersister(service).Instantiate(null, EntityMode.Poco) as T;
}

#endregion
}

The ISessionFactoryImplementor is one of the interfaces implemented by the NH SessionFactory. The method Resolve<T>(string) are using the parameter service as the entity-name. The hard-work is done by the method InitializeTypedPersisters; what I’m doing there is map each interface with its entity-name… nothing more.

Conclusions

“Program to an interface and not to an implementation” is really wonderful.

Do you really have some doubt about how NHibernate implements “Persistence ignorance” ?

Code available here.

21 October 2008

The power of ORM

In the last two years we saw many developers becoming from “DataSet world” to “ORM world” (thanks to Microsoft and it’s EntityFramework).

One of the most important challenge of ORM is the abstraction of your domain (entity classes of your business) from its persistent representation (tables in the DB).

To understand how NHibernate solve the ORM challenge I want start from an existing domain. The domain of this post:

public abstract class Animal
{
public virtual int Id { get; private set; }
public virtual string Description { get; set; }
}

public class Reptile: Animal
{
public virtual float BodyTemperature { get; set; }
}

public class Human : Animal
{
public virtual string Name { get; set; }
public virtual string NickName { get; set; }
public virtual DateTime Birthdate { get; set; }
}

public class Family<T> where T: Animal
{
public virtual int Id { get; private set; }
public virtual T Father { get; set; }
public virtual T Mother { get; set; }
public virtual ISet<T> Childs { get; set; }
}

The mapping of the previous post represent the domain in five tables:


OldDomain
 

Without touch my previous domain, and my previous test, I want represent it in two tables:


NewDomain
The new mapping is:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="EntityNameInAction"
namespace="EntityNameInAction"
default-access="backfield">

<
class name="Animal" abstract="true">
<
id name="Id">
<
generator class="hilo"/>
</
id>
<
discriminator column="kind"/>
<
property name="Description"/>

<
subclass name="Reptile">
<
property name="BodyTemperature"/>
</
subclass>

<
subclass name="Human">
<
property name="Name"/>
<
property name="NickName"/>
<
property name="Birthdate" type="Date"/>
</
subclass>
</
class>

<
class name="Family`1[[Reptile]]" entity-name="ReptilesFamily"
table="Families" discriminator-value="Reptile" where="familyKind = 'Reptile'">
<
id name="Id">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" class="Reptile" cascade="all"/>
<
many-to-one name="Mother" class="Reptile" cascade="all"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId"/>
<
one-to-many class="Reptile"/>
</
set>
</
class>

<
class name="Family`1[[Human]]" entity-name="HumanFamily"
table="Families" discriminator-value="Human" where="familyKind = 'Human'">
<
id name="Id">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" class="Human" cascade="all"/>
<
many-to-one name="Mother" class="Human" cascade="all"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId"/>
<
one-to-many class="Human"/>
</
set>
</
class>
</
hibernate-mapping>
The difference in the Animal hierarchy mapping is trivial and well known by NH users. What is more interesting is the work to persist Family<T> classes. Because I’m using the same table (Families) I need something to discriminate the tow concrete types Family<Reptile> and Family<Human>. In this case I can’t say that Family<Reptile> is a subclass of something else (in my domain I don’t have a superclass for Family<T>) by the way I can use a simple trick. The use of <discriminator>, discriminator-value and where tags is the trick.
Goal achived by NH: same domain, same test, two different persistent representations.
Code available here.

18 October 2008

El placer de un Bug Fix

Después de tantas líneas de código escritas en NHibernate (según las estadísticas de ohloh van más de 130000 solo en el core de NH) aún encuentro placer en arreglar bugs.

El placer se incrementa cuando, rastreando un bug, me encuentro con comentarios bastante detallados en puntos críticos donde, por varios motivos, había tomado una determinada decisión sobre la implementación de una funcionalidad de Hibernate3.2. En el caso de NHibernate, que es un porting, estas cosas son las que denomino: licencias poéticas. La misma definición la uso cuando alguien toma un patrón y lo implementa como le parece.

En NH encontré y arreglé unas cuantas licencias poéticas y, despacito, despacito, me permití también tomarme mis licencias poéticas (hay veces que el TDD te lleva a eso).

Realmente es un placer cuando aparece un bug que me lleva a arreglar una licencia poética y más aún si también me permite transformar un TODO en DONE… ni hablar si eso arregla dos bugs de un solo fix.