c# - NHibernate: Invalid Cast(检查你的映射属性类型不匹配);

标签 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: 

Message=Nie można rzutować obiektu typu 'NHibernate.Collection.Generic.PersistentGenericSet1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]' na typ Iesi.Collections.Generic.ISet1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]'.

意思是这样的:

Message=Cannot cast 'NHibernate.Collection.Generic.PersistentGenericSet1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]' to type Iesi.Collections.Generic.ISet1[Shop.Domain.Model.ProductCategory.ProductCategoryModel]'

我做错了什么?我读了很多类似的主题,但我仍然不知道错误在哪里。 附言 抱歉我糟糕的英语 ;)

最佳答案

对于最新的 4.0+ NHibernate 版本,我们应该牢记真正重要的变化,在此处描述,在这个 Q & A

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

** Known BREAKING CHANGES from NH3.3.3.GA to 4.0.0.GA

NHibernate now targets .Net 4.0. Many uses of set types from Iesi.Collections have now been changed to use corresponding types from the BCL. The API for these types are slightly different.

所以 - 现在我们要使用 System 而不是 iesi 东西,例如:

System.Collections.Generic.ISet<T>

第二件事非常重要,我们需要创建双向映射,一对多多对一。这意味着我们不能

// 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>
...

如我们所见,我们可以为多对一 (引用)属性 (值类型或字符串)。其中之一必须是只读的(insert="false"update="false")

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

关于c# - NHibernate: Invalid Cast(检查你的映射属性类型不匹配);,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29634277/

相关文章:

nhibernate - 流畅的 NHibernateWhere 子句

sql - 覆盖 NHibernate 中的删除行为

c# - 创建新的多维数组并用其他数组的值填充它

c# - 输入字符串在 double.Parse 中的格式不正确

c# - 如何使用泛型类型的子类初始化泛型属性?

generics - 如何在结构本身不需要通用参数的通用impl block 中添加类型注释?

swift - 检查 Swift 通用数字是否高于其最大值的特定百分比

c# - 何时使用锁定的指南

c# - 如何为数据容器实现 "Do I Need To Save"机制?

.net - 序列化的 NHibernate 配置对象 - 检测过时或按需重建?