Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

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

This entry was posted in NHibernate. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • KRIssh

    what the helll

  • Some user

    The other XML Schema elements in Spring.NET are the same as in Spring.Java’s DTD except for specifying string based key value pairs. In Java this is represented by the java.util.Properties class and the xml element is name as shown below

    The magic property The funny property In .NET the analogous class is System.Collections.Specialized.NameValueCollection and is represented by the xml element . The listing of the elements also follows the .NET convention of application configuration files using the element with ‘key’ and ‘value’ attributes. This is show below




    The error has something to do with key value pair.

  • Anna

    I had the same error: “The given key was not present in the dictionary”.
    For me the solution turned out to be that I had made a mistake in the many-to-one mapping.
    In the ‘class=’ bit I had referred to the right class, but to the wrong namespace…

  • Johan

    Double HAH, had the same issue. However mine was infact an embedded resource. My problem was that I named my mapping file incorrectly without the hbm bit. So instead of FileName.hbm.xml I had FileName.xml.

    DOH!

  • Jaysan

    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 :)

  • Matt Cole

    Thanks heaps for this!

  • http://www.flux88.com Ben Scheirman

    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.

  • http://www.stevideter.com/ Stevi Deter

    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…

  • Kyle Baley

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

  • http://www.ayende.com/Blog/ Ayende Rahien

    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.