将未知数量的列映射到Dictionary

时间:2009-03-23 10:19:57

标签: c# .net nhibernate mapping

我有一个遗留系统,可以在需要时动态扩充带有其他列的表。现在我想通过C#/ NHibernate访问所述表 没有办法改变遗留系统的行为,我动态地需要使用附加列中的数据。因此,动态组件映射不是一种选择,因为我不知道其他列的确切名称。

有没有办法将所有未映射的列放入字典(列名作为键)?或者,如果这不是一个选项,将所有列放入字典?

同样,我不知道编译时列的名称,所以这必须是完全动态的。

示例:

public class History
{
    public Guid Id { get; set; }
    public DateTime SaveDateTime { get; set; }
    public string Description { get; set; }
    public IDictionary<string, object> AdditionalProperties { get; set; }
}

因此,如果表历史记录包含列 Id SaveDateTime 描述 A B C D 我想在IDictionary中有“A”,“B”,“C”和“D”。或者,如果这太难了,只需将所有列放在那里。

首先,如果有帮助,我也可以使用字符串列。

6 个答案:

答案 0 :(得分:1)

您可能需要ADO.NET查询才能获取此数据。如果使用NH,即使使用SELECT *进行SQL查询,也不会获得列名。

您可以尝试使用SMO(SqlServer管理对象,SqlServer的.NET端口)或其他方式查找表定义。然后使用Fluent NHibernate和动态组件构建映射。在使用会话工厂后,我不确定是否可以更改映射。值得一试。祝你好运: - )

答案 1 :(得分:1)

我想使用以下代码,您可以在Hashtable中获得结果:

var hashTable = (Hashtable)Session.CreateSQLQuery("SELECT * FROM MyTable")
    .SetResultTransformer(Transformers.AliasToEntityMap)
    .UniqueResult();

显然,您的所有数据都将从会话中分离出来......

答案 2 :(得分:0)

我认为您可以做的最好的事情是在运行时查找列,为这些额外列创建映射,然后将输出写入xmlfile。完成后,您可以在运行时添加映射...

ISessionFactory sessionFactory = new Configuration()
                  .AddFile("myDynamicMapping.hbm.xml")

如何使用此映射是一个很好的问题,因为您必须动态创建类,然后才能使用SOL

祝你好运。

答案 3 :(得分:0)

在NHibernate中无法实现sql中无法实现的功能。

无法在插入查询中写入插入未知列。

答案 4 :(得分:0)

我假设您的程序在启动时通过读取XML文件构建单个Configuration对象,然后使用Configuration对象构建ISessionFactory对象。

然而,您的程序可以向数据库发送查询以找出此表上的任何额外列,而不是读取XML文件,构建Configuration对象并将其调用一天,然后更改Configuration,在将DynamicMapping对象编译为Configuration之前,以编程方式向ISessionFactory添加列。

答案 5 :(得分:0)

NHibernate确实有获取数据库模式的方法,前提是数据库类型/方言支持它。它主要由SchemaExport和SchemaUpdate函数使用。

如果你不害怕让你的手有点脏;

首先查看Configuration类中的GenerateSchemaUpdateScript函数: https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs

特别是,您对此类感兴趣,该类在该方法中引用: https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Tool/hbm2ddl/DatabaseMetadata.cs

DatabaseMetadata对象允许您遍历数据库中所有表和字段的元数据,从而可以确定哪些字段未映射。如果再次查看Configuration类,它会在TableMappings集合中保存它的映射列表。从GenerateSchemaUpdateScript函数中获取提示,您可以将TableMappings中的Table对象与实现DatabaseMetadata.GetTableMetadata函数返回的ITableMetadata的任何对象进行比较,以确定哪些列未映射。

使用此信息然后在运行时重建“动态”类使用的映射文件,将所有动态/运行时字段放在映射文件的“AdditionalProperties”动态组件部分中。映射文件需要作为外部文件而不是嵌入式资源包含在内,但这可以通过Configuration AddFile函数实现。重建后,重新加载配置,最后重建会话工厂。

目前看起来像Firebird,MsSQL Compact,MsSQL,MySQL,Oracle,SQLite和SybaseAnywhere都有ITableMetadata的实现,所以只能使用其中一个(除非你自己实现)。