代码之家  ›  专栏  ›  技术社区  ›  Tom Bushell

如何使用Fluent NHibernate自动映射列表<float>或float[]?

  •  1
  • Tom Bushell  · 技术社区  · 15 年前

    我已经成功地运行了一个示例程序,现在开始 与Fluent Nhibernate一起做真正的工作-尝试在我的项目类中使用自动应用 继承权。

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

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

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

    我不希望自动应用在数组上工作,但还是尝试过了, 一开始有些成功。每个数组都自动映射到一个blob (使用sqlite),这似乎是一个可行的解决方案。

    第一个问题是当我尝试在 包含数组的对象-我得到“float[]没有持久器” 例外情况。

    所以我的下一个想法是把我所有的数组转换成ilist,例如

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

    但现在我明白了:

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

    因为自动应用可以处理复杂对象的列表,所以它永远不会 在我看来,它无法映射基本类型的列表。但是 在谷歌搜索解决方案后,情况似乎是这样的。 有些人似乎已经解决了这个问题,但是示例代码 锯需要更多的知识,氨气比我现在有-我 不明白。

    问题:

    1。我怎样才能使这个工作与自动应用?

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

    如果需要的话,我可以修改我的应用程序来使用(尽管我更喜欢 列表)。

    编辑:

    我已经学习了密码 Mapping Collection of Strings 我看到在源代码中有一个测试代码,它设置了一个字符串列表,例如

    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 回复  |  直到 13 年前
        1
  •  2
  •   Tom Bushell    13 年前

    自从我提出了我的问题,流畅的NHibernate团队已经解决了这个问题。

    现在可以自动映射C值类型(字符串、int、float等)的列表。

    只要确保你有最新版本的FNH。

    编辑

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

    此版本还将自动映射数组-float[]、int[]等。

    似乎把它们映射成了斑点。我认为这将比IList更有效,但还没有做任何分析来确认。

        2
  •  1
  •   joshperry    15 年前

    我可能会做一对多的关系,并使列表另一个表…

    但也许你需要重新考虑你的对象,还有一个rawx可以组成一个rawpoint吗?这将生成一个包含3列(parentID、x、y)的表。

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

    这就是使用像NHibernate这样的ORM的关键所在。在应用程序中手工执行所有查询和SQL组合时,添加表的维护和实现成本很高。由于NHibernate的成本几乎为0,因此利用RDBMS的优势,让NHibernate将丑陋的东西抽象出来。


    我看到您在映射数组时遇到的问题,首先尝试使用覆盖映射,看看它是否可以工作,然后如果希望automap工作,您可以创建一个约定覆盖。

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

    不确定这是否可行,我需要为这些东西配置一个NHibernate测试设置。

        3
  •  1
  •   Tom Bushell    15 年前

    我最终得到了一个可以工作的覆盖——见代码清单的结尾。重点是:

    • 一个名为dlsappoversordexportrundatamap的新映射类
    • 在中添加useOverridesFromAssemblyOf子句 创建会话工厂

    而且,事实证明(至少在1.0.0.594版本中)有一个非常大的自动应用的gotcha- 映射类(例如dlsappoverordexportrundatamap)不能与域类(例如dlsappoverordexportrundata)位于同一命名空间中!

    否则,NHibernate会抛出 “nhibernate.mappingException:(xmldocument)(2,4):XML验证错误:…” 完全没有迹象表明真正的问题是什么或在哪里。

    这可能是一个bug,可以在以后的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; 
        } 
    
        4
  •  0
  •   Tom Bushell    15 年前

    没有得到任何答案在这里或在流畅的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)
    )
    
    推荐文章