Version 2

    What version of Hibernate is NHibernate ported from?

    NHibernate 1.0 is a port of Hibernate 2.1. Some obscure features of Hibernate 2.1 are missing from NHibernate and a few simple features from Hibernate 3 are present. See Differences between Hibernate and NHibernate for more details.

    This means that the original (Java) Hibernate documentation and FAQs are also a good place to look for your NHibernate-related questions.

    I get an error saying No persisters found for MyClass

    This often happens when there is a typo in a mapping file, or when you forget to set the build action for the file to Embedded Resource in Visual Studio .NET.

    I've changed the mapping file, but still get the same error I was getting before - why isn't NHibernate reading the new mapping file?

    If you compile the mapping files into an assembly as an /Embedded Resource (my personal recommendation) and you use Visual Studio .NET 2003 for development, then you need to rebuild the project, not just build it if all that was changed is a hbm.xml file. VS.NET will not rebuild a project if only an embedded resource has changed - so the assembly still contains the old hbm.xml file.

    Why doesn't my proxy work?

    To be able to create a proxy for a class, the class should have its properties, methods and events declared as virtual. This is not required if the class is proxied through an interface it implements (specified using proxy="SomeInterface"). There is no code in NHibernate 1.0 to validate your proxy classes, but that will be added in NHibernate 1.1.

    NHibernate uses the library Castle.DynamicProxy that is part of the Castle Project. DynamicProxy generates IL - not modifying your IL - at runtime for a subclass of your class, or the IL to implement an interface.

    Is thread-local session a good pattern for ASP.NET?

    NO! One HttpRequest is not guaranteed to be serviced by the same thread. The Thread Local Session pattern is a good pattern when your code controls the thread pool. This is a good blog from Scott Hanselman about why.

    There are multiple ways to approach this problem. The best place to store the ISession is in the Context collection. How you retrieve the ISession is a matter of preferences. You can write a wrapper that mimics TLS and is specific to ASP.NET, you can pass the ISession to your DAOs, or you can ...

    Also check out Using NHibernate with ASP.NET.

    Does NHibernate modify my IL? If not, how do you know what has changed?

    No, it does not modify your IL in anyway. Your IL remains exactly as it was when you compiled it.

    When an object is loaded by NHibernate the ISession keeps a snapshot of the state of your object. When you Flush() the ISession NHibernate compares that snapshot to the current state of the object. The appropriate changes are written to the database.

    How do I translate the NHibernate collections to .NET collections?

    The names of the collection mappings is one obvious place where the differences between Java and .NET are shown. Java's collection library has many more options than System.Collection does.

    • The <list> maps directly to an IList.
    • The <map> maps directly to an IDictionary.
    • The <bag> maps to an IList. A <bag> does not completely comply with the IList interface because the Add() method is not guaranteed to return the correct index. An object can be added to a <bag> without initializing the IList. Make sure to either hide the IList from the consumers of your API or make it well documented.
    • The <set> maps to an Iesi.Collections.ISet. That interface is part of the Iesi.Collections assembly distributed with NHibernate.

    If an order-by attribute is added to the collection mapping element then the concrete collection type will change to one that supports maintaining the order an element was added. For a <bag> it still uses an ArrayList. For the <map> and <set> that have an order-by attribute the concrete collection class changes to a Specialized.ListDictionary and Iesi.Collections.ListSet, respectively. This should be a non-issue since the consumers of your API are using the interfaces IList and Iesi.Collections.ISet.

    If a sort attribute is added to the collection mapping element then the concrete collection type will change to one that supports ordering. For the <map> and <set> that have a sort attribute the concrete collection class changes to a SortedList or Iesi.Collections.SortedSet, respectively, that uses the IComparer provided in the sort attribute. This should be a non-issue to the consumers of your API since they are using the interfaces IList and Iesi.Collections.ISet.

    Using an order-by or sort attribute does have implications on performance for maps and sets as the size of the collections grows. Please read the MSDN documentation about the ListDictionary and SortedList performance implications. There are also some good articles on The Code Project about collections.

    What is a persistent collection?

    This term is used in NHibernate to refer to a collection of its internal class (NHibernate.Collections.Set, List, Bag, etc.) which wraps a user's collection. All collections belonging to entities returned by NHibernate are persistent (= wrapped). Entities passed to Save also have their collections wrapped and replaced by the wrappers as a part of the saving process. Persistent collections have a snapshot of their original state and can therefore be updated more efficiently.

    Collections containing query results are not persistent, they are plain .NET collections (=ArrayList=s).

    NHibernate is deleting my entire collection and recreating it instead of updating the table.

    This generally happens when NHibernate can't figure out which items changed in the collection. Common causes are:

    • replacing a persistent collection entirely with a new collection instance
    • passing NHibernate a manually constructed object and calling Update on it.
    • serializing/deserializing a persistent collection apparently also causes this problem.
    • updating a <bag> with inverse="false" - in this case, NHibernate can't construct SQL to update an individual collection item.

    Thus, to avoid the problem:

    • pass the same collection instance that you got from NHibernate back to it (not necessarily in the same session),
    • try using some other collection instead of <bag> (<idbag> or <set>), or
    • try using inverse="true" attribute for <bag>.

    See also this question in Advanced Problems.

    I get a number of rows from the DB, work on some of them but when i do session.Flush() i see all the rows are updated.

    In general this problem occurs because of the presence of an <Enum> property in the class which is mapped as a <type="Int32"> or another numeric type.

    Remove the type attribute from the mapping and you should see an update only for those rows that you really worked on