Свободный Nhibernate HasMany - PullRequest
2 голосов
/ 04 июня 2010

У меня разрыв в понимании, и я был бы признателен за любую помощь.

Когда я создаю отношение HasMany, используя список, nhibernate создает столбец «index» в моей дочерней таблице.Если я запрашиваю таблицу, используя объединение, она выдает сообщение «Null Index on collection»

Что я не понимаю, так это то, как этот столбец «index» управляется / заполняется?

Мой соответствующий код:

Родитель (Продукт)

  Class:
       public class License
       {
             ...
             public virtual IList<License>  Licenses { get; set; }
             public Product()
             {
                Licenses = (IList<License>)new List<License>();
             }
       }

   Mapping:

    HasMany<License>(x => x.Licenses)
        .Inverse()
        .Not.LazyLoad()
        .AsList()
        .Cascade.AllDeleteOrphan()
        .ForeignKeyCascadeOnDelete()
        .KeyNullable()
        .KeyColumn("Product_ID")

Ребенок (лицензия):

  Class:
       public class License
       {
             ...
             public virtual Product_ID {get; set;}
       }

  Mapping: 


    ...
    References<Product>(x => x.Product_ID)
        .Column("ParentProduct");
    ...

И мое присоединение:

   criteria.Add(Restrictions.Disjunction()
                        .Add(Restrictions.Like("Name", kw))
                        .Add(Restrictions.Like("Description", kw)))
                        .CreateAlias("Licenses", "License",   NHibernate.SqlCommand.JoinType.LeftOuterJoin);

Я получаю:

[HibernateException: null index column for collection: Test.Licenses]
   NHibernate.Persister.Collection.AbstractCollectionPersister.ReadIndex(IDataReader rs, String[] aliases, ISessionImplementor session) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Persister\Collection\AbstractCollectionPersister.cs:703
   NHibernate.Collection.PersistentList.ReadFrom(IDataReader rs, ICollectionPersister role, ICollectionAliases descriptor, Object owner) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Collection\PersistentList.cs:120
   NHibernate.Loader.Loader.ReadCollectionElement(Object optionalOwner, Object optionalKey, ICollectionPersister persister, ICollectionAliases descriptor, IDataReader rs, ISessionImplementor session) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:706
   NHibernate.Loader.Loader.ReadCollectionElements(Object[] row, IDataReader resultSet, ISessionImplementor session) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:385
   NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:326
   NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:453
   NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:236
   NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:1649
   NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) in D:\source\elysium\Elysium.Web\FNH\src\NHibernate\Loader\Loader.cs:1568
...

РЕДАКТИРОВАТЬ

Я изменил коллекцию на Bag (или Set), и у меня возникла другая проблема:

Line 30:        public void SetPropertyValues(object target, object[] values)
Line 31:        {
Line 32:            setDelegate(target, values, setterCallback);
Line 33:        }
Line 34: 


Source File: D:\source\Test\FNH\src\NHibernate\Bytecode\Lightweight\AccessOptimizer.cs    Line: 32

Stack Trace:

[InvalidCastException: Specified cast is not valid.]
   (Object , Object[] , SetterCallback ) +409
   NHibernate.Bytecode.Lightweight.AccessOptimizer.SetPropertyValues(Object target, Object[] values) in D:\source\Test\FNH\src\NHibernate\Bytecode\Lightweight\AccessOptimizer.cs:32
   NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values) in D:\source\Test\FNH\src\NHibernate\Tuple\Entity\PocoEntityTuplizer.cs:292

[PropertyAccessException: Invalid Cast (check your mapping for property type mismatches); setter of Test.License]
   NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values) in D:\source\Test\FNH\src\NHibernate\Tuple\Entity\PocoEntityTuplizer.cs:296

... Когда я отыскиваю его, кажется, что проблема в том, что мой дочерний класс:

Лицензия публичного класса {

public virtual Guid Id { get; private set; }
...
public virtual Guid Product_ID { get; set; }

}

Но он пытается поместить экземпляр класса Parent в поле Product_ID.Таким образом, он пытается сопоставить Product_ID с экземпляром класса Product.Таким образом, я получаю продукт, содержащий массив лицензий, и он хочет, чтобы каждая лицензия в массиве содержала экземпляр родительского продукта.

Ответы [ 2 ]

5 голосов
/ 07 июня 2010

Нельзя использовать Inverse () вместе с упорядоченной коллекцией (например, списком) - если вы хотите упорядочить ее, вам нужно опустить Inverse () и сохранить ее из родительского элемента

1 голос
/ 04 июня 2010

Попробуйте сопоставить его как неупорядоченную коллекцию (сумка):

HasMany<License>(x => x.Licenses)
    .Inverse()
    .Not.LazyLoad()
    .AsBag()
    .Cascade.AllDeleteOrphan()
    .ForeignKeyCascadeOnDelete()
    .KeyNullable()
    .KeyColumn("Product_ID")

Отредактировано, чтобы добавить:

Вы не должны определять внешний ключ для дочернего объекта в дополнение к определению объекта многие-к-одному через References. Поэтому лицензия должна быть:

   public class License
   {
         ...
         public virtual Product {get; set;}
   }

Кроме того, я предполагаю, что вы имели в виду Product здесь, и приведение не требуется, потому что List<T> реализует IList<T>:

   public class Product
   {
         ...
         public virtual IList<License>  Licenses { get; set; }
         public Product()
         {
            Licenses = new List<License>();
         }
   }

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...