Saturday, April 30, 2011

NHibernate – The Good, the Bad, and the Ugly, that it gets!

A data access layer usually consumes 30% of the development time. A reasonable ORM can save you 90% of that 30% time. One such big hit is NHibernate.
Steps to use NHibernate:
  • Decide - Model first, Database first, or Code first
  • Create Mapping
  • Configuration
  • Query!

Pros:
  • Caching
  • Detached object
  • Concurrency
  • Interceptors
  • Batch processing
  • Attributes
  • Fluent Syntax
  • Database independency
  • Pretty mature, and large community
  • Open source
  • Model classes are POCO
Cons:
  • No visual modeler
  • Alot of mapping code that requires to be put into
  • Classes must have a no-arg constructor
  • Classes should have a  private Long id;
  • Classes may have private database attributes
  • Clumsy mapping/configuration files
Note that, to handle mappings/configurations, Fluent NHibernate is there. Fluent NHibernate is not a replacement for NHibernate or LINQ but merely a helper library that helps you configure NHibernate in code rather than using XML files; Fluent NHibernate defines helper classes which significantly facilitate the task of providing the correct configuration.
  • No good LINQ to NHB! still under development – very, very young!
  • Stored procedures in NHB; challenging.
  • Increased startup time due to metadata preparation ( not good for desktop like apps)
  • Huge learning curve, especially for those having no ORM background.
  • Pretty challenging to fine-tune the generated sql. For instance, see following SQL:
  •    1: SELECT    this_.[CHEQUE_ID] as CHEQUE1_0_1_, this_.[CHEQUE_TYPE_ID] as CHEQUE2_0_1_, this_.[BATCH_ID] as BATCH3_0_1_, this_.[ENTRY_DATETIME] as ENTRY4_0_1_, this_.[STATE_ID] as STATE5_0_1_, this_.[MICR_AMOUNT] as MICR6_0_1_, 
       2:         this_.[CHEQUE_NUMBER] as CHEQUE7_0_1_, this_.[PHEONIX_REFERENCE_NUMBER] as PHEONIX8_0_1_, this_.[ACCOUNT_NUMBER] as ACCOUNT9_0_1_,this_.[ACCOUNT_TITLE] as ACCOUNT10_0_1_, this_.[BRANCH_CODE] as BRANCH11_0_1_, this_.[ENTITY_ID] as ENTITY12_0_1_, this_.[FRONT_IMAGE] as FRONT13_0_1_, this_.[BACK_IMAGE] as BACK14_0_1_, this_.[IS_LINKED] as IS15_0_1_, this_.[CHEQUE_AMOUNT] as CHEQUE16_0_1_, 
       3:         this_.[LINKED_CHEQUE_NUMBER] as LINKED17_0_1_, this_.[LINKED_ACCOUNT_NUMBER] as LINKED18_0_1_, this_.[LINKED_CHEQUE_AMOUNT] as LINKED19_0_1_, this_.[LINKED_BENEFICIARY_ACCOUNT_NUMBER] as LINKED20_0_1_, this_.[EXCEPTION_DESCRIPTION] as EXCEPTION21_0_1_, this_.[OWNER_VERIFIER] as OWNER22_0_1_, this_.[CUSTOMER_TYPE_CODE] as CUSTOMER23_0_1_, this_.[IS_STOPPED] as IS24_0_1_, this_.[IS_OVERDRAW] as IS25_0_1_, this_.[LOCK_DATETIME] as LOCK26_0_1_, this_.[DEPOSIT_BANK] as DEPOSIT27_0_1_, this_.[AVAILABLE_BALANCE] as AVAILABLE28_0_1_, this_.[LINKED_DEPOSITED_BRANCH] as LINKED29_0_1_, this_.[LINKED_CHEQUE_NAME] as LINKED30_0_1_, b1_.[CHEQUE_ACTIVITY_ID] as CHEQUE1_1_0_
       4:         , b1_.[CHEQUE_ID] as CHEQUE2_1_0_, b1_.[ACTIVITY_TYPE_ID] as ACTIVITY3_1_0_, b1_.[Status] as Status4_1_0_, b1_.[REJECTION_REASON_ID] as REJECTION5_1_0_, b1_.[IS_OVERDRAW] as IS6_1_0_, b1_.[TRANSFER_AMOUNT] as TRANSFER7_1_0_, b1_.[Description] as Descript8_1_0_, b1_.[ACTIVITY_DATETIME] as ACTIVITY9_1_0_, b1_.[USER_ID] as USER10_1_0_, b1_.[ACCOUNT_NUMBER] as ACCOUNT11_1_0_
       5:         , b1_.[UserId] as UserId12_1_0_ FROM [CPS_CHEQUE] this_ inner join [CPS_CHEQUE_ACTIVITY] b1_ on this_.[CHEQUE_ID]=b1_.[CHEQUE_ID] 
  • Hard to get session management right if used in non-typical environments ( read non webapps )
  • Not suited for apps without a clean domain object model ( no all apps in world dont need clean domain object models) .
  • Have to jump through hoops if you have badly designed ( legacy ) db schema.
You might find this interesting to know that, NHibernate is also marketed by the term “multi-database support”; this means, you *can* move from one engine to another (from SQL Server to Oracle); but this does not mean that you can connect to both the databases at a time. For instance, query from Oracle and save into the SQL Server; for this you will have to create another set of configuration file!

ADO.NET Nhibernate
Test # Operation Time (ms) NH
1 100 Reads 000.609 000.859
2 100 Reads - 3 Joins 001.844 Couldnt apply 3 level join in HQL! ツ
3 100 Inserts 000.422 000.516
4 100 Updates 000.109 000.078
5 100 Reads - 1 Join 000.328 000.781
image
FIG1: ADO.NET vs NHibernate

Happy coding! Btw, you may also like to refer to my other articles on similar topic:

 

7 comments:

  1. I think it is ridiculous to compare ADO.net with NHibernate. You have to compare two things that provide the same services. Besides NHibernate uses Ado.net in behind.

    ReplyDelete
  2. Anonymous7:01 PM

    No is not ridiculous, you must compare it to see how must lag you add to fetch the data.

    ReplyDelete
    Replies
    1. Anonymous4:00 PM

      No, it is ridiculous. ADO.NET is not an ORM. It's like comparing a web server application like IIS with the TCP/IP stack instead of comparing it with another web server like Apache. Both products use the TCP/IP stack, much like NHibernate uses ADO.NET. How about a comparison with an actual ORM, like Lightspeed or Entity Framework ?

      Delete
  3. Anonymous5:40 AM

    True. However, it would also make sense to compare it with Entity Framework and/or another ORM tool to see how it performs.

    ReplyDelete
  4. Anonymous9:49 AM

    nHibernate is dying

    ReplyDelete
  5. Anonymous1:38 AM

    http://izlooite.blogspot.ae/2010/03/ef4-adonet-entity-framework-v40.html

    ReplyDelete
  6. Anonymous1:40 AM

    http://izlooite.blogspot.ae/2010/04/orm-market-analysis.html

    ReplyDelete

Related Posts

Popular Posts