我有一个遗留系统,可以在需要时动态扩充带有其他列的表。现在我想通过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”。或者,如果这太难了,只需将所有列放在那里。
首先,如果有帮助,我也可以使用字符串列。
答案 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的实现,所以只能使用其中一个(除非你自己实现)。