I have a gridview that is bound to the result from an nhibernate query. If the first item in the list is edited the following exception is thrown:
System.Refle
I don't use my domain objects in directly in the views. Instead I use the MVVM pattern and create suitable view models that holds non-proxied objects.
Very late, but should help others with the same problem. The solution I used is to wrap a custom list (in this case a NotificationList) around the field in the getter.
private IList<IParameter> _parameters = new List<IParameter>();
get
{
return new NotificationList<IParameter>(_parameters);
}
This list is a wrapper around the list, so that databinding will be forwarded to the original list.
public class NotificationList<T> : IList, IList<T>
{
IList<T> myList;
public NotificationList(IList<T> list)
{
myList = list;
}
int IList.Add(object item)
{
myList.Add ((T) item);
}
// implement both IList<T> and IList
// ...
}
For me this fixed the issue with the databinding, but created a side effect where every time the session was flushed all the items in the collection get updated in the DB, wether they changed or not. To resolve that, I changed the mapping to access the field directly. See this on Hibernate, which applies to NHibernate as well.
This is the new (Fluent) mapping:
HasMany(x => x.Parameters)
.Cascade.All()
.Access.CamelCaseField(Prefix.Underscore);
Is the root cause due to a proxy object in the list (from lazy loading) or because the list isn't homogeneous (contains multiple types even if they belong to the same class hierarchy)? The problem with non-homogeneous data sets is a known limitation. See this and this.
I don't think there's a solution other than to not use databinding to populate the grid. That's easy enough if it's read-only.
Another solution is to Join Fetch the relation if you know you are going to be Databinding it. E.g. add .SetFetchMode("People", FetchMode.Join). NHibernate should return only domain objects since none of them should be lazy loaded.
Maybe too late, but I'd just like to throw this into the ring, here is a solution that I've used for this.
It is also called 'SafeBindingList' like the other suggestion above, but, it does not 'clone' objects to solve the problem. It looks at the objects in the list, then if none proxied, the list is returned unmodified. If one or more objects are proxied, it adds an empty proxy to the non-proxied objects, thus making them all the same type.
So, instead returning a List[T] to bind to, use SafeBindingList[T] to ensure all objects have the same type.
This is updated for the version of Castle used with NH2.0.1: http://code.google.com/p/systembusinessobjects/source/browse/trunk/System.BusinessObjects.Framework/Data/SafeBindingLists.cs
Also, credit goes to the original code and poster: https://forum.hibernate.org/viewtopic.php?t=959464&start=0&postdays=0&postorder=asc&highlight=