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”。或者,如果这太难了,只需将所有列都扔在那里。

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

4

6 回答 6

1

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

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

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

于 2009-10-20T09:15:42.300 回答
1

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

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

于 2009-04-15T06:57:19.773 回答
0

What's not possible in sql is not possible in NHibernate.

It's not possible to write in insert query to insert into unknown columns.

于 2009-06-14T10:39:35.423 回答
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 的对象进行比较,以确定哪些列未映射。

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

目前,Firebird、MsSQL Compact、MsSQL、MySQL、Oracle、SQLite 和 SybaseAnywhere 似乎都有 ITableMetadata 的实现,因此只能使用其中一种实现(除非您自己实现)。

于 2009-06-17T07:07:01.473 回答
0

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

但是,您的程序无需读取 XML 文件、构建Configuration对象并每天调用它,而是可以向数据库发送查询以找出该表上的任何额外列,然后以编程Configuration方式将列添加到将对象DynamicMapping编译为.ConfigurationISessionFactory

于 2009-06-15T03:29:19.643 回答
0

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

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

你将如何使用这个映射是一个很好的问题,因为你必须动态创建你的类,然后你就是 SOL

祝你好运。

于 2009-06-13T04:17:34.787 回答