有没有在NHibernate中正确定义版本属性的技巧?

时间:2010-10-04 16:41:02

标签: c# nhibernate nhibernate-mapping

我正在尝试使用NHibernate来映射使用decimal(9,0)(~32位整数)“版本属性”的遗留数据库(用于每行的乐观锁定)。

这些字段在数据库中声明为可空,并在NHibernate参考手册的5.1.7节中声明:

  

版本号可以是Int64,Int32,Int16,Ticks,Timestamp或TimeSpan(或者它们可以为空的对应物)类型   在.NET 2.0中。)

...所以我将它们映射为int?版本属性。

我的地图文档与此类似:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Model" assembly="Model" xmlns="urn:nhibernate-mapping-2.2">
    <class name="Bar" lazy="true" table="`BAR`" schema="`dbo`">
        <id name="ID" access="property" column="`ID`">
            <generator class="assigned" />
        </id>
        <version name="Version" column="`VERSION`" type="int?" />
        <!-- ... etc ... -->
    </class>
</hibernate-mapping>

然而,在运行时,这种情况失败了,例外情况类似于:

failed: NHibernate.MappingException : Could not compile the mapping document: Model.Mappings.Bar.hbm.xml
  ----> NHibernate.MappingException : Could not determine type for: Model.int?,  for columns: NHibernate.Mapping.Column(VERSION)
    at NHibernate.Cfg.Configuration.LogAndThrow(Exception exception)
    at NHibernate.Cfg.Configuration.AddValidatedDocument(NamedXmlDocument doc)
    at NHibernate.Cfg.Configuration.ProcessMappingsQueue()
    at NHibernate.Cfg.Configuration.AddDocumentThroughQueue(NamedXmlDocument document)
    at NHibernate.Cfg.Configuration.AddXmlReader(XmlReader hbmReader, String name)
    at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
    at NHibernate.Cfg.Configuration.AddResource(String path, Assembly assembly)
    at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
    Core\DAOUtils.cs(33,0): at Core.DAOUtils.OpenSession()
    test\cs\FooTest.cs(65,0): at DataModel.Tests.FooTest.TestSelectStar()
    --MappingException
    at NHibernate.Mapping.SimpleValue.get_Type()
    at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.BindProperty(HbmVersion versionSchema, Property property, IDictionary`2 inheritedMetas)
    at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.BindVersion(HbmVersion versionSchema, PersistentClass rootClass, Table table, IDictionary`2 inheritedMetas)
    at NHibernate.Cfg.XmlHbmBinding.RootClassBinder.Bind(XmlNode node, HbmClass classSchema, IDictionary`2 inheritedMetas)
    at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.AddRootClasses(XmlNode parentNode, IDictionary`2 inheritedMetas)
    at NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.Bind(XmlNode node)
    at NHibernate.Cfg.Configuration.AddValidatedDocument(NamedXmlDocument doc)

是否有一些技巧可以正确使用NHibernate的版本属性,或者我做错了什么?

对我来说奇怪的是,NHibernate似乎将我的程序集/命名空间名称附加到int?类型的开头,这似乎是错误的。

修改

将映射文件更改为使用int而不是int?后,我现在遇到以下异常:

System.InvalidCastException : Unable to cast object of type 'NHibernate.Type.DecimalType' to type 'NHibernate.Type.IVersionType'.
    at NHibernate.Tuple.PropertyFactory.BuildVersionProperty(Property property, Boolean lazyAvailable)
    at NHibernate.Tuple.Entity.EntityMetamodel..ctor(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory)
    at NHibernate.Persister.Entity.AbstractEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory)
    at NHibernate.Persister.Entity.SingleTableEntityPersister..ctor(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping mapping)
    at NHibernate.Persister.PersisterFactory.CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, IMapping cfg)
    at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
    at NHibernate.Cfg.Configuration.BuildSessionFactory()

不幸的是,NHibernate在这里没有给我一个非常详细的错误信息(很高兴知道数百个类中的哪个类正在抛出这个),而且我无法说服log4net工作,所以我暂时不知所措。

编辑#2:

总结“技巧”:

  • 假设整数版本属性(并且即使它们在数据库中声明为decimal),请确保在映射XML中将所有版本属性声明为int。 (虽然如果在POCO中宣布int?,它应该有效)
  • 确保没有版本属性设置为decimal类型(在POCO或映射XML中)

1 个答案:

答案 0 :(得分:1)

你不应该包括'?'在映射中 - 而不是写入类型=“Int32”。如果您的POCO中的财产可以为空,那么它应该可以正常运作。 (至少它适用于属性 - 我没有尝试过可以使用可以为空的版本列...)。