Lesser-Known NHibernate Features: Entity Mode Map

This one is a real treat!

When we use NHibernate or any other O/RM, we normally use classes to represent the database objects (tables or views). In NHibernate, this is called Entity Mode POCOPlain Old CLR Object. NHibernate, however, supports other Entity Mode: Map. This Entity Mode does not use “physical” classes, but instead, dictionaries (implementations of IDictionary)! This makes it great for mapping dynamic database objects without the need for real classes.

For creating a Map entity, we need to do a slight change in our usual mappings, here is a simple Parent-Child example:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <hibernate-mapping namespace="Succinctly.Model" assembly="Succinctly.Model" xmlns="urn:nhibernate-mapping-2.2">
   3:     <class entity-name="Parent" table="`PARENT`">
   4:         <id name="Name" column="`NAME`" type="String" length="50" generator="assigned"/>
   5:         <set name="Children" lazy="true" inverse="true" cascade="all-delete-orphan">
   6:             <key column="`PARENT_NAME`" not-null="true"/>
   7:             <one-to-many entity-name="Child"/>
   8:         </set>
   9:     </class>
  10:     <class entity-name="Child" table="`CHILD`">
  11:         <id name="Name" column="`NAME`" type="String" length="50" generator="assigned"/>
  12:         <many-to-one name="Parent" entity-name="Parent" column="`PARENT_NAME`" not-null="true"/>
  13:     </class>
  14: </hibernate-mapping>

You might not have noticed that I used entity-name instead of name in the <class> declaration, in <one-to-many> and <many-to-one>; this tells NHibernate that these classes will be mapped as Map, not POCO (the default). Alas, you cannot use mapping by code, because there is no physical class to map.

OK, so now we have a mapped Parent and Child. We insert them as this:

   1: using (var session = sessionFactory.OpenSession())
   2: {
   3:     var parent = new Hashtable { { "Name", "Parent Name" } };
   4:     parent["Children"] = new HashSet<Object> { new Hashtable { { "Name", "Child Name" }, { "Parent", parent } } };
   5:  
   6:     session.Save("Parent", parent);
   7:     session.Flush();
   8: }

I am using Hashtable as an IDictionary implementation, but you might as well use Dictionary<TKey, TValue>. It doesn’t really matter.

As for retrieving, also simple, just use the ISession methods that take an entityName parameter:

   1: var parentProxy = session.Load("Parent", "Parent Name") as IDictionary;
   2:  
   3: var parent = session.Get("Parent", "Parent Name") as IDictionary;

Each of these IDictionary instances will have an entry that has key “$type$” and contains the entity type name – in our case, either “Parent” or “Child” – as well as entries for each of the other mapped properties, associations and collections:

   1: var name = parent["Name"] as String;
   2: var children = parent["Children"] as ISet<Object>;

Entity Mode Map supports both HQL and Criteria querying APIs:

   1: var parentsByCriteria = session.CreateCriteria("Parent").Add(Restrictions.Eq("Name", "Parent Name")).List();
   2:  
   3: var parentsByHQL = session.CreateQuery("from Parent where Name = :name").SetParameter("name", "Parent Name").List();

And it also supports executable HQL:

   1: session.CreateQuery("delete from Child").ExecuteUpdate();

Cool, don’t you thing? Eat your heart out, Unnamed Framework! Winking smile

                             

No Comments

Add a Comment

As it will appear on the website

Not displayed

Your website