Feature Post

Top

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:

 

6 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. Anonymous25 April

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

    ReplyDelete
  3. Anonymous30 June

    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. Anonymous24 October

    nHibernate is dying

    ReplyDelete
  5. Anonymous18 June

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

    ReplyDelete
  6. Anonymous18 June

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

    ReplyDelete