【问题标题】:nHibernate Exception: Unable to cast object of typenHibernate 异常:无法转换类型的对象
【发布时间】:2011-02-04 19:09:37
【问题描述】:

我在保存对象时遇到了 nHibernate 错误。

涉及的类有:

interface IHardwareSpecification
{
   //fields and methods
} 

public class CPUSpecification : IHardwareSpecification
{
    //fields and methods
}    

public class SystemTransaction 
{       
    //Bunch of other fields

    private IHardwareSpecification _specs;
    public virtual IHardwareSpecification Specification 
    { 
        get { return _specs; }
        set { _specs = value;} 
    }
 }

映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" ...>
  <class name="SystemTransaction" table="SystemTransactions" lazy="false">
    <component access="field.camelcase-underscore" name="Specification"
               class="HardwareMarketplace.Model.CPUSpecification">
      <property access="field.camelcase-underscore" column="Specification_Rate"
                name="Rate"/>
         ...
    </component>
  </class>
</hibernate-mapping >

在通过 Save 将对象持久化到数据库时,我收到以下错误:

异常:无法将“Castle.Proxies.IHardwareSpecificationProxy”类型的对象转换为“Hardwaremarketplace.Model.SystemTransactions.CPUSpecification”类型。

我正在尝试找出解决此问题的方法,因此我们将不胜感激。 f

【问题讨论】:

  • @Diego CPUSpecification 是一个值对象,因此没有映射。我没有 IHardwareSpecification 的映射。
  • 到目前为止我注意到的唯一错误是该字段名为“_specs”,但映射中的名称是“规范”。根据您的访问设置,该字段应命名为“_specification”。否则我无法重现您的问题。更多信息可能会有所帮助。
  • 在您尝试保存实体之前,不知何故为“规范”属性分配了“IHardwareSpecificationProxy”类型的对象。这就是问题的根源。我看不出 nHiberante 创建该代理的理由。在保存之前如何初始化实体?
  • @AlexD 使用 AutoMapper 将 WCF Web 服务 SystemTransactionDTO 数据协定映射到 SystemTransaction 模型实体。

标签: c# nhibernate object-persistence


【解决方案1】:

根据您的评论,我了解 AutoMapper 为接口属性 Specification 创建代理类型。 这样你就有了:

public class CPUSpecification : IHardwareSpecification { }

和

public class IHardwareSpecificationProxy : IHardwareSpecification{ }

这是两种不兼容的类型,IHardwareSpecificationProxy 对象无法转换为CPUSpecification。

您需要做的是告诉 AutoMapper 使用 CPUSpecification 类而不是动态代理。

编辑: 考虑到SystemTransactionDTO 内部有CPUSpecificationDTO,您可以使用以下代码实现您所需要的:

Mapper.CreateMap<SystemTransactionDTO, SystemTransaction>();
Mapper.CreateMap<CPUSpecificationDTO, CPUSpecification>();
Mapper.CreateMap<CPUSpecificationDTO, IHardwareSpecification>()
    .ConvertUsing(dto => Mapper.Map<CPUSpecificationDTO, CPUSpecification>(dto));

并且无需将Specification 属性类型更改为CPUSpecification:)。

【讨论】:

  • 谢谢 - 我不知道。您是否建议我将自动映射器映射 Mapper.Map"CPUSpecificationDTO, IHardwareSpecification" 更改为 Mapper.Map"CPUSpecificationDTO, CPUSpecification" (这也意味着将 SystemTransaction 类的 Specification 属性更改为 CPUSpecification 类型)?
  • 从我编辑的答案中可以看出,您不必更改 Specification 属性来键入 CPUSpecification。只需告诉 AutoMapper 在转换为 IHardwareSpecification 时使用转换为 CPUSpecification 即可。此建议是否有助于您解决问题?
  • 是的,我尝试使用此方法进行映射以从 SystemTransaction 转换为 SystemTransactionDTO - 我收到一条错误消息,指出参数类型 IHardwareSpecification 不可分配给 CPUSpecification 类型
猜你喜欢
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
相关资源
最近更新 更多