NHibernate Save – System.ArgumentNullException: Collection cannot be null

by Oliver 22. July 2011 18:45

Today I hit a quite subtle bug setting up persistence for our soon-to-appear new todo management tool. Since we’re building on ASP.NET 4 I simply used the ISet<T> and HashSet<T> types in the System.Collections.Generic namespace for all entity collections, e.g.

  1: using System.Collections.Generic;
  2: namespace Teamaton.TodoCore.Entities
  3: {
  4:     public class Group
  5:     {
  6:         public ISet<Person> Members { get; set; }
  7:         public string Name { get; set; }
  8:     }
  9: }

But when I called _session.Save(entity) I got the following error:

image

At first I thought: oh, yeah, of course! I didn’t initialize my Members property! No problem.

So I added a simple constructor to initialize all my ISet<T> properties like this:

  1: public Group()
  2: {
  3:     Members = new HashSet<Person>();
  4: }

I still go the same error. Well, there were quite a few of these collections and I went and added constructors of the same kind everywhere.

Ran the code again – still the same ol’ error! Arrrrg!

Ok, Google to the rescue: http://www.google.com/search?q=nhibernate+System.ArgumentNullException%3A+Collection+cannot+be+null lead me to NHibernate custom collection options, an interesting read although not really to the point. But wait: there, towards the end, I finally found the essential piece of information I was missing:

Note: the custom collection also has to implement ICollection because ICollection<T> doesn’t implement ICollection

so you get an exception like the following when you try to save.

[ArgumentNullException: Collection cannot be null.
Parameter name: c]
   System.Collections.ArrayList..ctor(ICollection c) +10067700

Well, the same is true for ISet<T>: it does not implement ICollection! So when NHibernate performs its internal collection magic and is passed a reference to a collection of type HashSet<T> which implements ISet<T> and even ICollection<T> it throws an error because it really expects an ICollection. And then I remembered, that I’ve tried using the System.Collections.Generic classes with NHibernate before and it didn’t work because it internally uses the Iesi.Collections.

So I had to change my HashSet<T> to HashedSet<T>, reference the Iesi.Collections.dll and all was well! ISet<T> is defined in Iesi.Collections as well, so I didn’t have to change that.

Happy Coding!

enjoyed the post?

Tags:

Comments are closed

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for javascript. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our children. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.