你如何使用Fluent NHibernate自动化List <float>或float []?</float>

时间:2009-11-06 21:59:49

标签: nhibernate list fluent-nhibernate automapping

成功获得示例程序后,我现在开始了 使用Fluent NHibernate进行实际工作 - 尝试在我的项目类中使用Automapping 层次结构。

这是一个科学的仪器应用程序,我的课程 映射具有几个属性,这些属性是浮点数组,例如

    private float[] _rawY; 
    public virtual float[] RawY 
    { 
        get 
        { 
            return _rawY; 
        } 
        set 
        { 
            _rawY = value; 
        } 
    } 

这些数组最多可包含500个值。

我没想到Automapping会在阵列上运行,但无论如何都试过了, 起初取得了一些成功。每个数组都自动映射到BLOB (使用SQLite),这似乎是一个可行的解决方案。

第一个问题出现在我试图调用SaveOrUpdate时 包含数组的对象 - 我得到了“没有浮点数为浮点数[]” 例外。

所以我的下一个想法是将我的所有数组转换为IList,例如

public virtual IList<float> RawY { get; set; } 

但现在我明白了:

NHibernate.MappingException: Association references unmapped class: System.Single 

由于Automapping可以处理复杂对象的列表,因此它永远不会 发生在我身上,它将无法映射基本类型的列表。但 在做了一些谷歌搜索解决方案之后,情况似乎就是如此。 有些人似乎已经解决了问题,但是示例代码我 锯子需要比我现在更多的NHibernate知识 - 我 不明白。

问题:

1。如何通过自动映射实现此功能?

2。此外,为此应用程序使用数组或列表是否更好?

如果需要,我可以修改我的应用程序(虽然我更喜欢 列表)。

修改

我已经研究了Mapping Collection of Strings中的代码,我发现源代码中有测试代码设置了一个字符串的IList,例如。

public virtual IList<string> ListOfSimpleChildren { get; set; }

[Test] 
public void CanSetAsElement() 
{ 
    new MappingTester<OneToManyTarget>() 
        .ForMapping(m => m.HasMany(x => x.ListOfSimpleChildren).Element("columnName")) 
        .Element("class/bag/element").Exists(); 
} 

所以这一定是可以使用纯自动映射,但我没有运气得到任何工作,可能是因为我没有必要的知识手动映射NHibernate。

开始认为我将不得不破解这个(通过将浮点数组编码为单个字符串,或者创建一个包含单个浮点数的类,然后我将其聚合到我的列表中),除非有人能告诉我如何正确地做到这一点。

结束修改

这是我的CreateSessionFactory方法,如果这有助于制定一个 回复......

    private static ISessionFactory CreateSessionFactory() 
    { 
        ISessionFactory sessionFactory = null; 


        const string autoMapExportDir = "AutoMapExport"; 
        if( !Directory.Exists(autoMapExportDir) ) 
            Directory.CreateDirectory(autoMapExportDir); 


        try 
        { 
            var autoPersistenceModel = 
                AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
                       .Where(t => t.Namespace == "DlsAppAutomapped") 
                       .Conventions.Add( DefaultCascade.All() ) 
                ; 


            sessionFactory = Fluently.Configure() 
                .Database(SQLiteConfiguration.Standard 
                              .UsingFile(DbFile) 
                              .ShowSql() 
                         ) 
                .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
                                             .ExportTo(autoMapExportDir) 
                         ) 
                .ExposeConfiguration(BuildSchema) 
                .BuildSessionFactory() 
                ; 
        } 
        catch (Exception e) 
        { 
            Debug.WriteLine(e); 
        } 


        return sessionFactory; 
    } 

4 个答案:

答案 0 :(得分:2)

自从我发布问题以来,Fluent NHibernate团队已经解决了这个问题。

现在,您可以自动执行C#值类型的IList(字符串,整数,浮点数等)。

请确保您拥有最新版本的FNH。

修改

我最近从FNH 1.0升级到FNH 1.3。

此版本还将自动化数组 - float [],int []等

似乎将它们映射为BLOB。我认为这比IList更有效,但没有做任何分析来确认。

答案 1 :(得分:1)

我可能会做一对多的关系,并将列表另一个表格......

但也许您需要重新考虑您的对象,是否还有一个可以组成RawPoint的RawX?这将创建一个包含3列(ParentID,X,Y)的表。

不连续性来自于希望将List映射到RDBMS中不会非常整齐地放入列中的值。表实际上是用于存储数据列表的方法。

这是使用像NHibernate这样的ORM的重点。在您的应用程序中手动执行所有查询和SQL组合时,添加表在维护和实现方面的成本很高。使用NHibernate,成本几乎为0,因此利用RDBMS的优势,让NHibernate抽象出丑陋。


我看到你映射数组的问题,首先尝试使用覆盖映射并查看它是否可行,然后你可以创建一个约定覆盖,如果你想让automap工作。

.Override<MyType>(map =>
{
    map.HasMany(x => x.RawY).AsList();
})

不确定这是否有效,我需要为这些东西配置一个nHibernate测试设置。

答案 2 :(得分:1)

我最终获得了覆盖工作 - 请参阅代码清单的结尾。关键点是:

  • 一个名为DlsAppOverlordExportRunDataMap的新映射类
  • 在中添加了UseOverridesFromAssemblyOf子句 CreateSessionFactory

另外,事实证明(至少在1.0.0.594版本中)有一个非常大的问题与自动映射 - 映射类(例如DlsAppOverlordExportRunDataMap)不能与域类在同一个命名空间中(例如DlsAppOverlordExportRunData)!

否则,NHibernate将抛出“NHibernate.MappingException:(XmlDocument)(2,4):XML验证错误:......”,绝对没有迹象表明真正的问题是什么或在哪里

这可能是一个错误,可能会在Fluent NHibernate的更高版本中修复。

namespace DlsAppAutomapped
{
    public class DlsAppOverlordExportRunData
    {
        public virtual int Id { get; set; }

        // Note: List<float> needs overrides in order to be mapped by NHibernate. 
        // See class DlsAppOverlordExportRunDataMap.
        public virtual IList<float> RawY { get; set; } 
    }
}


namespace FrontEnd
{
    // NEW - SET UP THE OVERRIDES
    // Must be in different namespace from DlsAppOverlordExportRunData!!!
    public class DlsAppOverlordExportRunDataMap : IAutoMappingOverride<DlsAppOverlordExportRunData>
    {
        public void Override(AutoMapping<DlsAppOverlordExportRunData> mapping)
        {
            // Creates table called "RawY", with primary key
            // "DlsAppOverlordExportRunData_Id", and numeric column "Value"
            mapping.HasMany(x => x.RawY)
                   .Element("Value");
        }
    }
}

    private static ISessionFactory CreateSessionFactory() 
    { 
        ISessionFactory sessionFactory = null; 


        const string autoMapExportDir = "AutoMapExport"; 
        if( !Directory.Exists(autoMapExportDir) ) 
            Directory.CreateDirectory(autoMapExportDir); 


        try 
        { 
            var autoPersistenceModel = 
                AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
                       .Where(t => t.Namespace == "DlsAppAutomapped")

                       // NEW - USE THE OVERRIDES    
                       .UseOverridesFromAssemblyOf<DlsAppOverlordExportRunData>() 

                       .Conventions.Add( DefaultCascade.All() ) 
                ; 


            sessionFactory = Fluently.Configure() 
                .Database(SQLiteConfiguration.Standard 
                              .UsingFile(DbFile) 
                              .ShowSql() 
                         ) 
                .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
                                             .ExportTo(autoMapExportDir) 
                         ) 
                .ExposeConfiguration(BuildSchema) 
                .BuildSessionFactory() 
                ; 
        } 
        catch (Exception e) 
        { 
            Debug.WriteLine(e); 
        } 


        return sessionFactory; 
    } 

答案 3 :(得分:0)

这里没有得到任何答案,或者在Fluent NHibernate邮件列表中没有得到任何答案,所以这就是我所做的。

它闻起来像一个可怕的黑客,但它的工作原理。 (它是否会扩展到大型数据集还有待观察)。

首先,我在一个类中包含了一个float属性(名为Value):

// Hack - need to embed simple types in a class before NHibernate
// will map them
public class MappableFloat
{
    public virtual int Id { get; private set; }
    public virtual float Value { get; set; }
}

然后我在其他类中声明需要浮点数列表的属性,例如

public virtual IList<MappableFloat> RawYMappable { get; set; }

NHibernate创建一个具有多个外键的数据库表,例如

create table "MappableFloat" (
    Id  integer,
   Value NUMERIC,
   DlsAppOverlordExportRunData_Id INTEGER,
   DlsAppOverlordExportData_Id INTEGER,
   primary key (Id)
)