Common Mistakes and Anti-Patterns in NHibernate

nhibernate

What are the most common mistakes and anti-patterns NHibernate user programmers make? Please explain why those are bad practices or give link to resource for further reading.

For example:

  • One anti-pattern common for new NHibernate programmers is to use identity/native POID's instead of ORM style onces. Read more here…

Best Answer

My personal "frequently explained" issues:

Anti-Patterns

Messing around with detached objects (SaveOrUpdate or Merge plus some messy code) instead of using DTO's. The more complex the entities are, the messier the code is. (It also means that it works quite well with trivial entities.) Ayende also calls it the Stripper Pattern and explains the encapsulation issue.

Not understanding persistence ignorance and writing NH applications as when using explicit SQL. Symptom of that: calling Update after changing an object, wondering why changes are persisted even if Update had not been called, wondering how to avoid changes to be persisted.

Not understanding transactions and the unit of work pattern. Frequent anti-patterns: implicit transactions, session-per-operation and session-per-application. Some more reading:

Using NH events to put application logic in (eg. change tracking in insert and update triggers)

Create one class per table. Some people don't understand OOD, others don't understand relational design.

Mistakes

use of one-to-one instead of many-to-one. I tried it to explain in this answer.

Using join fetch in combination with SetMaxResult. My latest answers related to that topic:

Writing self changing entities. When an entity doesn't exactly return the value that had been set by NH, it is considered dirty and gets updated in every session. For instance: replacing the NH persistent collection in a property setter.

  IList<Address> Addresses
  {
    get { return addresses; }
    // will cause the addresses collection to be built up from scratch
    // in the database in every session, even when just reading the entity.
    set { addresses = new List<Address>(value); }
  }

  int Whatever
  {
    // will make the entity dirty after reading negative values from the db.
    // this causes unexpected updates after just reading the entity.
    get { if (whatever < 0) return 0; }
    set { whatever = value; }
  }

May be more is following.