C# 将未知数量的列映射到字典

C# 将未知数量的列映射到字典,c#,.net,nhibernate,mapping,C#,.net,Nhibernate,Mapping,我有一个遗留系统,可以在需要时用附加列动态扩充表。现在我想通过C/NHibernate访问上述表格。 没有办法改变遗留系统的行为,我需要动态地处理附加列中的数据。因此,动态组件映射不是一个选项,因为我不知道附加列的确切名称 有没有办法将所有未映射的列作为键放入字典列名中?或者如果这不是一个选项,将所有列放入字典 同样,我在编译时不知道列的名称,所以这必须是完全动态的 例如: public class History { public Guid Id { get; set; } p

我有一个遗留系统,可以在需要时用附加列动态扩充表。现在我想通过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; }
}
因此,如果表History包含Id、SaveDateTime、Description、A、B、C和D列,我希望在IDictionary中包含A、B、C和D列。或者,如果这太难做到,只需将所有列都放在那里


对于初学者,如果有帮助的话,我也可以只使用字符串列。

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


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

我认为你能做的最好的事情就是在运行时找到这些列,为这些额外的列创建一个映射,然后将输出写入一个XML文件。完成后,您可以在运行时添加映射

ISessionFactory sessionFactory = new Configuration()
                  .AddFile("myDynamicMapping.hbm.xml")
如何使用这个映射是一个很好的问题,因为您必须动态地创建类,然后才能使用它


祝你好运

在sql中不可能的东西在NHibernate中是不可能的


无法写入insert查询以插入未知列。

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


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

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

如果你不怕弄脏你的手

首先查看Configuration类中的GenerateSchemaUpdateScript函数:

特别是,您会对该类感兴趣,该类在该方法中引用:

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

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


目前看来Firebird、MsSQL Compact、MsSQL、MySQL、Oracle、SQLite和SybaseAnywhere都有针对ITableMetadata的实现,因此只有使用其中一种实现才有可能,除非您自己实现。

我想通过以下代码,您可以在哈希表中获得结果:

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

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

尽管可以动态检测和处理表元数据。并相应地修改insert语句。可以使用此信息使用经典ado.net更改和/或动态组装insert语句。问题是:使用NHibernate可以做到这一点吗?或者NHibernate是否提供了某种形式的自动化来做到这一点。我不这么认为,但我不确定。您可以尝试询问nhibernate用户组