Blog Home  Home Feed your aggregator (RSS 2.0)  
NHibernate – not all that glitters is gold - Manuel Abadia's ASP.NET stuff
 
# Monday, September 24, 2007

NHibernate is a popular and free ORM tool. It is based on the java version, called Hibernate, which is also very popular in the Java world.

However, NHibernate (I’m talking about version 1.2.0 GA here) has some limitations. Some of them that are in the top of my head at the moment:

1) It is heavily tied to the java version (Hiberante), so a lot of the request and/or enhancements are ignored. If the java version is not going to add it, probably it will not be added to NHibernate.
2) Hibernate was started in 2001, and was designed to overcome a lot of the ORM problems. During these years, it has solved a lot of those problems, but other still remain and they can’t be fixed without heavily changing its design.
3) Even if it is extensible, the IInterceptor interface does not expose all the events that can be interesting to capture (For example, events after loading, updating or deleting data). The only way to handle that at the moment is to implement the ILifecycle interface by the entity itself, losing entity transparency.
4) No paging support in some nontrivial scenarios.
5) There is no support for retrieving all the data at once for hierarchical queries.

Let’s see a simple example:

Imagine that I have some orders with their respective order items. I want a customer to be able to see all orders he has placed on the system, with their associated order items. As a customer can have a lot of orders, only 10 orders will be displayed per page.

ISession session = SessionFactory.OpenSession();
ICriteria criteria = session.CreateCriteria(typeof(MyOrder));
criteria.SetFirstResult(0);
criteria.SetMaxResults(10);
criteria.AddOrder(new Order("Id", true));
IList<MyOrder> orders = criteria.List<MyOrder>();

Using lazy fetch mode, NHibernate does:

Gets the first 10 orders using a single select statement.

Gets the order items for the first 10 orders using one select statement for each order.

Using subselect mode, NHibernate does:

Gets the first 10 orders using a single select statement.

Gets the order items for ALL the orders using a single select statement.

To clearly see what NHibernate does when using the join (eager fetch) mode, imagine that all orders have 3 order items.

In that case, what NHiberante does is a left outer join of the order and orderitems table, returning the first 10 rows of that join. That means that NHibernate returns only 4 orders, the first three with 3 order items each one, and the last one only with one order item. Take a look at the code, I was asking for 10 orders, and only got 4, and the fourth is not filled with its three order items, only with one!

I added this as a bug in the NHibernate bug tracker, and I received a quick reply of its main developer, Sergey Koshcheyev, confirming me that NHibernate wasn’t able to perform that query right because of the inner join, and didn’t know if it should raise an error in that case or not. Nearly the same time Ayende Rahien closed the case because that was the “expected behavior” because that is what is happening on the DB side and that there wasn’t any way to get the data I was asking for.

That response is completely wrong:

1) I’m asking NHibernate to get 10 orders and specifying a fetch strategy so what I should get is 10 orders. Depending on the fetch strategy NHibernate may perform one select, several selects, a join or whatever it needs to, but at least I expect to get 10 orders (if there are present in the database table).

2) It is possible to retrieve the proper data, and I added an example of how to do it in the bug report.  If NHibernate can’t handle it, that is another story…

You can take a look at my bug report and its resolution here and decide yourself if this was a good resolution or not:

http://jira.nhibernate.org/browse/NH-1123

If you have read Ayende’s blog you'll know that he has complained several times about how Microsoft Connects resolve some bugs (I agree that he is right and that they should be fixed), but after his bug resolution, it seems a bit ironical to see him complaining about that…

I see NHibernate as a great product (and free) but as its codebase was started in 2001, it has get old. I will continue to use it but I’m evaluating other alternatives (any suggestions (even if they are not free)?).

Searching out there, I found a project that has really impressed me: SqlAlchemy. This is the philosophy of the project:

SQL databases behave less and less like object collections the more size and performance start to matter; object collections behave less and less like tables and rows the more abstraction starts to matter. SQLAlchemy aims to accommodate both of these principles.

SQLAlchemy doesn't view databases as just collections of tables; it sees them as relational algebra engines. Its object relational mapper enables classes to be mapped against the database in more than one way. SQL constructs don't just select from just tables—you can also select from joins, subqueries, and unions. Thus database relationships and domain object models can be cleanly decoupled from the beginning, allowing both sides to develop to their full potential.

SqlAlchemy first release was in 2006. The first version did support what Nhibernate is not able to do:

http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping_limits

So it seems that it is possible after all…

I’m very impressed with SqlAlchemy. However, SqlAlchemy currently is only available for python. I hope it works properly with IronPython 2.0 (whenever it is released). Although a C# version using C# 3.0 features would be a killer.

You can see an example of the power of SqlAlchemy here:

http://spyced.blogspot.com/2007/01/why-sqlalchemy-impresses-me.html

For more information about SqlAlchemy visit:

http://www.sqlalchemy.org/

Monday, September 24, 2007 11:14:32 AM (Romance Daylight Time, UTC+02:00)  #    Comments [5]   NHibernate  | 
Monday, September 24, 2007 5:09:39 PM (Romance Daylight Time, UTC+02:00)
Tambien me gustaria saber alguna alternativa a nhibernate. Es triste cuando decides usar nhibernate en tu proyecto, ya que la cache de segundo nivel te puede ser muy util, y debido a que nhibernate para hacer bulks deletes, primero te carga todos los objetos y despues lo borra(uno a uno). Tomas la decision de llamar a pelo a ADO.net desde nhibernate, consiguiendo con esto que te cargas todas las regiones de la segunda cache(cualquier llamada a ADO.net, destroza en teoria la segunda cache).

Vamos que poco me ayudó...mientras no tenga deletes puedo usar la segunda cache omo dios manda. A ver si arreglan los bulk deletes y updates.
ASpanishGuy
Monday, September 24, 2007 5:18:59 PM (Romance Daylight Time, UTC+02:00)
También me encontré con ese problema y lamento decirte que no creo que lo solucionen. La respuesta que dieron fue algo así como: "esto es necesario para manejar correctamente las eliminaciones en cascada".

A mi entender, si una entidad no tiene asociaciones en cascada, no se porqué no pueden eliminarse con una sola sentencia SQL...
Saturday, September 29, 2007 10:49:18 PM (Romance Daylight Time, UTC+02:00)
For paging support take a look at this:
http://code.google.com/p/unhaddins/
http://code.google.com/p/unhaddins/wiki/LesTroisMousquetaires

Use SVN version.

Regards!
Monday, October 1, 2007 2:40:30 AM (Romance Daylight Time, UTC+02:00)
This is one of the best O/R mapping tools.
http://en.wikipedia.org/wiki/CodeGear_ECO

This is not only O/R tool, but uses ideology of Model Driven Architecture.

...still it also has some problems with SQL.
Newsgroup can be found here:
Most active group is here:
http://groups.google.com/group/borland.public.delphi.modeldrivenarchitecture.eco/topics

(use NNTP to post there).

Cheers,
Dmitriy.
Dmitriy Nagirnyak
Monday, October 1, 2007 9:02:35 AM (Romance Daylight Time, UTC+02:00)
Thanks for the link guys. I'm putting them in my list of things to look at
All comments require the approval of the site owner before being displayed.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

[Captcha]Enter the code shown (prevents robots):

Live Comment Preview
Copyright © 2019 Manuel Abadia. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.