NHibernate:无效的转换(检查您的映射是否存在属性类型不匹配);

时间:2015-04-14 17:58:26

标签: c# generics nhibernate

我有一个ProductCategoryModel类:

public class ProductCategoryModel
{
    public virtual int id { get; set; }
    public virtual string name { get; set; }
    public virtual int parentId { get; set; }
    public virtual Iesi.Collections.Generic.ISet<ProductCategoryModel> subCategory { get; set; }
}

这是我的映射xml:

    <?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Shop.Domain.Model.ProductCategory" assembly="Shop.Domain">
  <class name="ProductCategoryModel">
    <id name="id" column="id">
      <generator class="native" />
    </id>
    <property name="name" not-null="true" length="50" type="string" column="name"/>
    <many-to-one name="parentId" not-null="true" class="ProductCategoryModel" column="parentId"/>
    <set name="subCategory" inverse="true">
      <key column="parentId"/>
      <one-to-many class="ProductCategoryModel"/>
    </set>
  </class>
</hibernate-mapping>

我的数据库表包含:

id: 2, name: "...", parentId: 0
id: 3, name: "...", parentId: 2 
id: 4, name: "...", parentId: 2

现在我要选择ID为2的类别:

session1.Get<ProductCategoryModel>(id);

但是Nhibernate抛出异常:

        NHibernate.PropertyAccessException was unhandled
  HResult=-2146232832
  Message=Invalid Cast (check your mapping for property type mismatches); setter of Shop.Domain.Model.ProductCategory.ProductCategoryModel
  Source=NHibernate
  StackTrace:
       w NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
       w NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValues(Object entity, Object[] values)
       w NHibernate.Persister.Entity.AbstractEntityPersister.SetPropertyValues(Object obj, Object[] values, EntityMode entityMode)
       w NHibernate.Engine.TwoPhaseLoad.InitializeEntity(Object entity, Boolean readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent)
       w NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList hydratedObjects, Object resultSetId, ISessionImplementor session, Boolean readOnly)
       w NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer)
       w NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer)
       w NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
       w NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister)
       w NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId)
       w NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session)
       w NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session)
       w NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
       w NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
       w NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
       w NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
       w NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType)
       w NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType)
       w NHibernate.Impl.SessionImpl.Get(String entityName, Object id)
       w NHibernate.Impl.SessionImpl.Get(Type entityClass, Object id)
       w NHibernate.Impl.SessionImpl.Get[T](Object id)
       w Shop.Infrastructure.Repositories.ProductCategoryIM.GetCategoryById(Int32 id) w f:\Uczelnia\!Semestr VI\Kurs aplikacji bazodanowych\KubutShop2\KubutShop\Shop.Infrastructure\Repositories\ProductCategoryIM.cs:wiersz 58
       w Shop.Application.Front.FrontService.GetProductCategoryById(Int32 id) w f:\Uczelnia\!Semestr VI\Kurs aplikacji bazodanowych\KubutShop2\KubutShop\Shop.Application\Front\Front.cs:wiersz 139
       w Presentation.ConsoleApp.Program.Main(String[] args) w f:\Uczelnia\!Semestr VI\Kurs aplikacji bazodanowych\KubutShop2\KubutShop\Presentation.ConsoleApp\Program.cs:wiersz 40
       w System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       w System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       w Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       w System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       w System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       w System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       w System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidCastException
       HResult=-2147467262
       Message=Nie można rzutować obiektu typu 'NHibernate.Collection.Generic.PersistentGenericSet`1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]' na typ 'Iesi.Collections.Generic.ISet`1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]'.
       Source=Shop.Domain
       StackTrace:
            w (Object , Object[] , SetterCallback )
            w NHibernate.Bytecode.Lightweight.AccessOptimizer.SetPropertyValues(Object target, Object[] values)
            w NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
       InnerException: 
  

消息=Niemożnazutowaćobiektutypu'NHibernate.Collection.Generic.PersistentGenericSet 1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]' na typ Iesi.Collections.Generic.ISet 1 [Shop.Domain.Model.ProductCategory.ProductCategoryModel]'。

意味着这样的事情:

  

Message =无法强制转换'NHibernate.Collection.Generic.PersistentGenericSet 1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]' to type Iesi.Collections.Generic.ISet 1 [Shop.Domain.Model.ProductCategory.ProductCategoryModel]'

我做错了什么?我读了很多类似的话题,但我仍然不知道哪里出错。 附: 抱歉我的英语很差;)

1 个答案:

答案 0 :(得分:0)

使用最新的4.0+ NHibernate版本,我们应该记住这里所描述的真正重要的变化Q & A

让我引用一点(来自release notes):

  

**已知从NH3.3.3.GA到4.0.0.GA

的突然变化      

NHibernate现在的目标是.Net 4.0。 Iesi.Collections中集合类型的许多用法现在已更改为使用BCL中的相应类型。这些类型的API略有不同。

所以 - 现在我们即将使用 System 而非 iesi 的内容,例如:

System.Collections.Generic.ISet<T>

第二件事,非常重要的是,我们需要创建双向映射one-to-manymany-to-one。这意味着我们不能

// not iesi
// we need System
using System.Collections.Generic;
using System.Collections.ObjectModel;

...

public class ProductCategoryModel
{
    ...
    // could be used just as navigation property
    public virtual int parentId { get; set; }
    // This is must with inverse="true"
    public virtual ProductCategoryModel Parent { get; set; }
    // the System.Collections.Generic
    public virtual ISet<ProductCategoryModel> SubCategories { get; set; }
    ...

并映射:

...
// readonly
<property  name="parentId" not-null="true" column="parentId" type="string"
                                      insert="false" update="false" />
// inverse end
<many-to-one name="Parent" not-null="true" class="ProductCategoryModel" column="parentId"/>

<set name="SubCategories" inverse="true" batch-size="25">
  <key column="parentId"/>
  <one-to-many class="ProductCategoryModel"/>
</set>
...

我们可以看到,我们可以为many-to-one (参考)property (valueType or string)制作映射。其中一个必须是只读(insert =&#34; false&#34; update =&#34; false&#34;)

注意:不要忘记,因为我们使用逆,我们必须在C#中设置关系的两边...