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

4
我有一个遗留系统,当需要时会动态地为表添加额外的列。现在我想通过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包含列IdSaveDateTimeDescriptionABCD,我希望在IDictionary中有"A","B","C"和"D"。如果这太难做到了,可以将所有列都放进去。
首先,如果只使用字符串列,那也可以。
6个回答

1

我猜你可以通过下面的代码在Hashtable中获取你的结果:

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

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


1

你可能需要使用 ADO.NET 查询来获取这些数据。如果你使用 NH,即使使用 SELECT * 的 SQL 查询,你也无法获得列名。

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


0

我认为最好的方法是在运行时找到列,为这些额外的列创建映射,然后将输出写入XML文件。完成后,您可以在运行时添加映射...

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

如何使用此映射是一个很好的问题,因为您还必须动态创建您的类,那么就挂了。

祝你好运。


0

在SQL中不可能的事情,在NHibernate中也是不可能的。

无法编写插入查询以插入到未知列中。


虽然可以动态检测并处理表格元数据,然后相应地修改插入语句。可以使用这些信息使用“经典”ado.net来修改和/或动态组装插入语句。问题是:是否可以使用NHibernate来实现此操作?或者NHibernate是否提供某种形式的自动化来完成此操作。 - Tobias Hertkorn
我不确定,但我觉得不是。你可以尝试在 nhibernate 用户组上提问:http://groups.google.com/group/nhusers - Paco

0

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

然而,你的程序可以向数据库发送查询以确定此表上的任何额外列,然后在将Configuration对象编译为ISessionFactory之前,在DynamicMapping中以编程方式添加列,从而修改Configuration对象,而不是仅仅读取XML文件并完成构建Configuration对象的工作。


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的实现,因此只能在其中之一中实现(除非您自己制作实现)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接