Basic checks
Check Mapping files are embedded resources (right click the file in VS and select Properties. Ensure the build action is Embedded Resource)
Check the class is marked as Serializable
[Serializable]
public class Customer : DomainEntity<int>, ICustomer
{…}
public virtual Orders Orders
{
get
{
return this._orders;
}
set
{
this.orders = value;
}
}
Lazy loading exceptions
Check the object loaded is occurring in a session correctly and the session is being properly closed & committed
Check the mapping for the object and the children you are trying to load. If the Mappings are set to lazy=true, you will have to explicitly load them or access a property on the object to hydrate the object graph to the next lazy node down the object graph.
Check your session is not closing prematurely, either by code or by an internal error such as DB timeouts. Nested session will all be committed at the committing of the upper most transaction. Be wary of overly nested transaction as this may lead to time out and a possible “number of connection/cursor” exceptions throw from the database or it drivers.
Concurrency Issues
NHibernate is finicky with objects being loaded multiple times and associated in different sessions. This (in my cases) has usually come down to poorly factored code. E.g. Make sure you are not trying to put the same object in to a collection twice from 2 different sessions etc. I don’t have any great advice here as this is usually handled on a case by case basis, but is a good sign you need to rethink your design.
Rules of thumb
Reference data should be cached, immutable and eager loaded. This makes the pretty basic assumption that no relationships exist off to other objects (i.e. no children or other mapped entities)
Complex domain data should generally be lazy loaded, immutable and not cached. You can set up lazy/eager loading strategies on a per property basis. Eager loading simple types is fine, be careful with complex relationships as you should be catering for the most minimal requirements. Excessive use of eager loading will severely affect performance.
Again, be careful with eager loading. If you eager load a child there may be any number levels of eager loading down the object graph. Eager loading should generally be avoided unless there is a business reason to do so. Instead explicitly load each object or object collection explicitly in the business code that deals with the situation, ie
//this occurs with in a session to get all the Orders of the given customer
this.TheOrderDao.Initialize(customer.Orders); //Using NHibernateUtil.Initialize
Use ICriterion styled searches to do simple object searches, ie: Find all customers with city location of London
Use HQL queries to get type objects back from queries. These are general object based queries where a collection of a mapped type is returned but may need other joined tables for querying purposes. Ie return all the product categories for all the orders of customer x for the last 365 days. These queries can usually be though of as follow the format select customer.* from customer inner join….
Only use stored procs for set based queries to
aid in speed if walking the object graph would be extraneous or load too much redundant data
to return streamlined DTO/DataSet for non type queries or queries that would otherwise return overly large object graphs when only a small portion of the graph is required. (These are the exception rather than the norm.)
HTH
Rhys