views:

480

answers:

2

I want to use some of predefined lookups without roundrips to Database in NHibernate.

Basically I would like to have code like this:

public class Countries
{
  static Countries() {
    Australia = new Country
      {
          Id = 14,
          Description = "Australia"
      }
  }
  public static Country Austrlia { get; protected set }
}

Then write this code snippets:

address.Country = Countries.Australia;// Snippet1
if (address.Country == Countries.Australia) { // Snippet2
  // Do something
}

So I do override Equals, GetHashCode and even overload operators == and != for Country class lookup.

The Snippet1 works ONLY if the Country with given Id has not been loaded into memory. Otherwise it throws NonUniqueObjectException saying the object with given Id is already in memory.

To workaraound this I have to evict the loaded country and then assign the lookup value. This feels wrong and I'm not sure what will happen when the query for Country lookup will be executed again.

So the question is: How to maintain static lookup classes in NHibernate?

Thanks, Dmitriy.

+2  A: 

Check out what we call Enumeration classes..

It's basically the flyweight pattern.

You can persist them, using an IUserType implementation, as the value or the display name.

We do crazy stuff with them. Like provide auto-genned lookup tables with foreign keys for DBA folks while keeping all the values in code.

Matt Hinze
Thanks. Good one.But not exactly what I need. I'll try to be more precise:1) address.Country = Countries.AustraliaWHENaddress.Country has already been assigned and persisted. It causes NonUniqueObjectException.AND2) address.Country = Session.Get<Country>(UserSelectedIdFromScreen)WHEN:List of Countries is populated from Database and NOT from code. Only couple of predefined values are known in code. Others come from DB.
Dmytrii Nagirniak
+1  A: 

It seems NHibernate cannot handle 2 objects logically the same (but different instances).
So instead of mixing "static lookup" with Database lookups it is better to only use one of them.

In my case - lookups stored in the database. BUT to avoid roundtrip to the database just for the sake of obtaining the object it is only needed to use Load instead of Get:

address.Country = Session.Load<Country>(CountryIds.Australia); // This does not hit DB
address.Country = Session.Get<Country>(CountryIds.Australia); // This DOES hit DB
Dmytrii Nagirniak