CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Kyle Baley - The Coding Hillbilly

"We are stuck with technology when what we really want is just stuff that works" -- Douglas Adams

NHibernate error while adding a collection to an object

I'll keep this one fairly Google-able due to the amount of time it took me to figure it out sans a similar reference. Seasoned NHibernate veterans will likely guess the issue before they finish reading this sentence.

Here's the error message I was getting from NHibernate:


System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.

at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at NHibernate.Cfg.XmlHbmBinding.CollectionBinder.BindCollectionSecondPass(XmlNode node, Collection model, IDictionary`2 persistentClasses)
at NHibernate.Cfg.XmlHbmBinding.CollectionBinder.<>c__DisplayClassd.<AddCollectionSecondPass>b__c(IDictionary`2 persistentClasses)
at NHibernate.Cfg.Configuration.SecondPassCompile()
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at Trilogy.Gunton.DataAccess.SessionBuilder.GetSessionFactory(Database selectedDatabase) in SessionBuilder.cs: line 72
at Trilogy.Gunton.DataAccess.SessionBuilder.GetSession(Database selectedDatabase) in SessionBuilder.cs: line 21
at Trilogy.Gunton.DataAccess.UnitOfWorkFactory.Create() in UnitOfWorkFactory.cs: line 19
at Trilogy.Gunton.DataAccess.RepositoryBase`1.GetAll() in RepositoryBase.cs: line 19
at Trilogy.Gunton.Tests.Integration.JobTypeRepositoryFixture.Should_retrieve_job_types() in JobTypeRepositoryFixture.cs: line 16


This started happening after I added a collection to my object (which Karl Seguin's post was instrumental in getting set up). Here's what I added to the <class> element in the .hbm.xml file for the object (fingers crossed on the XML formatting):
  <bag name="Locations" generic="true">
       <key column="JobID" />
       <one-to-many class="RuralLocation" />
  </bag> 

Pretty standard stuff to those in the know (of which I am still not). I also created the corresponding RuralLocation class and RuralLocation.hbm files to go along with them.

So the above error would appear anytime I tried to get a session factory in NHibernate, which is pretty much the first thing that's done anywhere in the app. The ultimate solution: RuralLocation.hbm was not an embedded resource.

This is something I will forget to do about 75% of the time I create a new .hbm file but usually the error is more "oh yeah"-inducing. Something like "Can't find class Trilogy.Gunton.Domain.RuralLocation" where you can tell pretty quickly it's not loading the file properly. I know this because the way I discovered the problem is by creating an integration test to save a RuralLocation on its own, outside the context of its parent object.

In this case, because I went straight to using the new class in a collection within another object, the error was hair-tearingly cryptic. Luckily, I don't have much hair anyway so no harm done.

Kyle the Eggheaded


Published Mar 14 2008, 10:40 PM by Kyle Baley
Filed under:

Comments

Ayende Rahien said:

Klye,

Can you create a simple test case and add it to the JIRA.

I would consider this a bug. When NHibernate throws an error, it should _tell_ you what is going on.

Cryptic errors are a bug, period.

# March 14, 2008 11:49 PM

Kyle Baley said:

Damn, I *knew* you were going to ask me to do that... A sample will be forthcoming.

# March 15, 2008 12:10 AM

Stevi Deter said:

interesting. in java, you'll generally get a failure on app startup (and when your test case loads) when it tries to load the mapping for the parent object, complaining there's no mapping for the collection. at which point you bang your head and say, "i will finally learn to use the ant plugin that will automagically generate my hibernate cfg file to include all my hbm files for me."

or at least, *i* bang my head and *i* say...

# March 15, 2008 12:18 AM

Ben Scheirman said:

Kyle, if you keep forgetting to make it an embedded resource, then maybe you'd prefer to load them up as files rather than scanning the assembly for the mappings.

Use what makes you productive.

# March 17, 2008 8:58 AM

Matt Cole said:

Thanks heaps for this!

# April 14, 2008 10:08 AM

Jaysan said:

Hah, found this through Google after scratching my head for a few minutes and it fixed my problem right away. Funny enough it wasn't me that added the mapping file, but I probably wouldn't have thought to check for embedded resourceness. Thanks for the google friendly tip :)
# July 24, 2008 12:28 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

Our Sponsors