2013-08-02 3 views
0

Я использую BindingSource, чтобы заполнить форму из списка NHibernate:Nhibernate мешок с BindingSource

public class Customer{ 
    public string Name { get; set;} 
    public IList<Order> Orders { get; set;} 
} 

bindingSourceCustomer.DataSource = session.Query<Customer>().ToList(); 
bindingSourceOrder.DataSource = bindingSourceCustomer; 
bindingSourceOrder.DataMember = "Orders"; 

теперь, когда я называю

bindingSourceOrder.AddNew(); 

генерируется исключение:

Значение «System.Object» не относится к типу «Model.Order» и не может быть , используемым в этой общей коллекции.

Теперь я изменил первую строку:

bindingSourceCustomer.DataSource = session.Query<Customer>().Select(customer => 
    { 
     customer.Orders = customer.Orders.ToList(); 
     return customer; 
    }) 
    .ToList(); 

она работала, причина, почему, потому, что Nhibernate использует PersistentBag как реализация IList, которая, по-видимому не очень хорошо работает с источником связывания (Насколько я вижу).

Любое предложение о том, как заставить Nhibernate возвращать класс List или как решить проблему с источником привязки?

ответ

0

Это потому, что BindingSource не может обнаружить тип списка: Постоянный пакет NHibernate не имеет интерфейса ITypedList и свойства Indexer. Перед добавлением сопоставлений вам необходимо заменить NHibernate CollectionTypeFactory на пользовательский. я присоединять мою реализацию:

PersistentGenericBag:

public class EnhancedPersistentGenericBag<T> : PersistentGenericBag<T> , ITypedList 
{ 
     public EnhancedPersistentGenericBag(ISessionImplementor session, ICollection<T> coll) : base(session, coll) { } 

     public EnhancedPersistentGenericBag(ISessionImplementor session) : base(session) { } 

     public EnhancedPersistentGenericBag() { } 

     public new T this[int index] 
     { 
      get 
      { 
       return (T)base[index]; 
      } 
      set 
      { 
       base[index] = value; 
      } 
     } 

     public string GetListName(PropertyDescriptor[] listAccessors) { return GetType().Name; } 

     public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) 
     { 
      return TypeDescriptor.GetProperties(typeof(T)); 
     } 
    } 

CollectionTypeFactory:

public class EnhancedCollectionTypeFactory : DefaultCollectionTypeFactory 
{ 


    public override CollectionType Bag<T>(string role, string propertyRef, bool embedded) 
    { 

     return new EnhancedGenericBagType<T>(role, propertyRef); 
    } 

} 

GenericBagType:

public class EnhancedGenericBagType<T> : BagType 
    { 
     public EnhancedGenericBagType(string role, string propertyRef) : 
      base(role, propertyRef, false) { } 

     public override IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister, object key) 
     { 
      return new EnhancedPersistentGenericBag<T>(session); 
     } 

     public override IPersistentCollection Wrap(ISessionImplementor session, object collection) 
     { 
      return new EnhancedPersistentGenericBag<T>(session, (ICollection<T>)collection); 
     } 

     public override Type ReturnedClass 
     { 
      get 
      { 
       return typeof(ICollection<T>); 
      } 
     } 

     protected override void Add(object collection, object element) 
     { 
      ((ICollection<T>)collection).Add((T)element); 
     } 

     protected override void Clear(object collection) 
     { 
      ((ICollection<T>)collection).Clear(); 
     } 

     public override object Instantiate(int anticipatedSize) 
     { 
      if (anticipatedSize > 0) 
       return new List<T>(anticipatedSize + 1); 
      else 
       return new List<T>(); 
     } 
    } 

Как переопределить по умолчанию CollectionTypeFactory:

Configuration cfg = new Configuration(); 
cfg.CollectionTypeFactory<EnhancedCollectionTypeFactory>(); 
Смежные вопросы