0

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 クラスを返すようにする方法、またはバインディング ソースの問題を解決する方法について何か提案はありますか?

4

1 に答える 1

0

これは、BindingSource がリスト タイプを検出できないためです。NHibernate の永続バッグには、ITypedList インターフェイスも Indexer プロパティ public もありません。マッピングを追加する前に、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);
    }

}

汎用バッグの種類:

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>();
于 2014-04-01T15:26:21.733 に答える