Sunday, October 30, 2011

The ORM duo: NHibernate and the Fluent NHibernate


I was travelling to my native place when I came across few interesting people with whom interaction was very cute, though very short. The one amongst them was the bus conductor who was punching the tickets for the passengers. The ticket needs to be punched on specific numbers before it is given to any passenger. The conductor probably uses some meaningful mappings to assure the passenger about their journey details and payments. Though the passenger is not aware about the mappings, except their payment details, they are assured their payment has been noted in the database and a receipt is delivered back to them. The mappings are cryptic so as to reduce the misuse of the same ticket for the different journey.


NHibernate is the analogy. Before the existence of ORM tools the developer had to write the SQL statements manually to interact with the database. The organization also had to hire specialized SQL developers, apart from application programmers, to take care of generating database interactive layer for the application. The programming paradigm for both the technologies is very different. This differences gave rise to creation of ORM tools.

The paradigm of using ORM tools for developing database applications is widely accepted due to ease of the development of the database products. ORM tools helps the software developer to interact with the database using the syntax of the programming language. These tools forms the generic DAL layer for different types of database applications thereby abstracting the database centric code from the application developer. The application developer need not be aware of PL/SQL to interact with the database but instead of it, the ORM takes care of generating database specific code as per the code written by the application user using the ORM tool. The following diagram shows the entities and the database tables in the system. I will show the code snippets more than write-ups for this post.



NHibernate is the open source ORM tool which takes care of the code generation for object-relational mappings. This tool works on the concepts of mappings which are stored in XML format. The mapping files are embedded into the assembly and is used to map POCO objects to the database objects at runtime. Typically, the mapping files often contains the map of POCO objects and the database objects with their relations.



The mapping files are very cumbersome to create and maintain and hence the developer may tend to make a lot of mistakes while writing the mapping files manually. The task of writing the mapping files are often taken away from the developer and pushed to the ORM veteran. This triggered the need for creating the custom library which takes care of mapping the domain model with the database without suffering from the hassles of writing the XML files.


The fluent NHibernate is the library which takes care of configuring NHibernate assemblies to work easily with your application code. The library mainly contains wrapper functions that takes care of configurations and mappings of the nHibernate library functions without having to create mapping files manually (a wizard like Harry Potter).



Let's discuss the process of creating the entities, their mappings and configuration using fluent NHibernate.


Entity:



The entity is the plain C# class with all the properties marked as virtual. The entity should have a unique identifier (Id) to uniquely identify itself.


Mapping:



The class for the mapping of the entity is inherited from ClassMap of the fluent NHibernate. These classes contains the mapping for all the properties of the entity class in its constructor. It also defines the database table that the entity maps to.



The class for the mapping of the component (unlike entity the component does not have unique identity in the database, they are associated to the entity for its persistence) inherits from the ComponentMap.


Configuration:



The configuration of the fluent NHibernate is done using Fluently namespace. It creates the new configuration object using Configure() which allows the developer to specify the database and mappings configuration to build the NHibernate session factory. The session factory is tightly bound to specific database. The NHibernate can be configured to work with multiple databases by creating different session factory objects.


Let's have a look at the CRUD operations using Nhibernate:


Create/update:



The create and update can be done with NHibernate using its SaveOrUpdate() in the current active session. The code shown above creates the new entity in the database if it does not already exists otherwise it updates the particular entity in the database. This is achieved using the internal map of NHibernate. When the call to SaveOrUpdate() is made the NHibernate checks its internal map to identify the database row for a particular domain entity. It then creates the appropriate SQL statement to achieve desired output.


Read:



The NHibernate uses DetachedCriteria class to generate SQL query. The above example creates the query on the Book entity and filters the results based on Title and Author. The DetachedCriteria should be bounded to a NHibernate session object before it is executed. The execution of the SQL query happens with the call of List().


The test cases for the above code is as follows:



The test cases are self explanatory. If you are new to the unit testing then please refer to my post at: http://pratikrpatel.blogspot.com/2011/03/unit-testing-stay-focused-on-your-code.html


The process of writing mapping files is quite cumbersome for the developers because it follows the XML standards with is very different from the application programming standards. The fluent NHibernate assembly is a wrapper façade (ref: http://en.wikipedia.org/wiki/Facade_pattern) that generates the mapping files automatically based on the C# code. It eases the load of the developer to create xml files manually.


The process of generating database schema based on the domain model goes hand-in-hand with the application domain model. The Nhibernate provides tools which can create the database schema automatically based on the mappings. The SchemaExport class located under NHibernate.Tool.hbm2ddl namespace. The sample code for generating DB schema is shown below:



The evolution of ORM tools may greatly reduce the developer's effort of writing database code. It also ensures that the developer can interact with the database seamlessly. The ORM tools include other features like connection management, caching, etc. which enables developer to interact with the database effectively.

Cave Inimicum, Colloportus!

No comments: