我正在寻找一些方法来使用nhibernate在我的应用程序中动态映射数据库表类(或者如果其他一些ORM工作然后让我知道)。我对nhibernate相当新,但我过去使用过实体框架。
我的大多数应用程序都将使用静态结构和流畅的nhibernate来映射它们。
但是,需要创建多个数据库表并将其映射到每个安装站点的对象。这些都将作为基本结构(id,name等),但是根据它们捕获的数据类型,它们将具有其他字段。从一些阅读中我发现我可以使用xml中的“动态组件”映射来使用IDictionary Attributes属性添加字段。这是第一步,看起来相对简单。参考(http://ayende.com/blog/3942/nhibernate-mapping-dynamic-component)
第二步是我在努力的地方。我需要根据客户的需要定义表并映射它们。如上所述,每个表都有一组静态属性和一些动态属性。他们还需要引用静态“位置”类,如下所示
位置(STATIC)(id,coordinates)
----- DynamicTable1(DYNAMIC)(id,Name,location_id,DynamicAttribute1,DynamicAttribute2 ........)
----- DynamicTable2(DYNAMIC)(id,Name,location_id,DynamicAttributeA,DynamicAttributeB ....)
我们需要能够根据客户需要创建/映射尽可能多的DynamicTable。对于大多数客户端站点,DynamicTable1,DynamicTable2等在某些方面很可能会有所不同。在nhibernate中有没有办法实现这一目标?数据库中表格的创建/管理将在其他地方进行管理,我只需要一些方法将其映射到我的ORM中。
一些背景知识 该应用程序将用于存储地质数据。由于地质数据根据地点而存在固有的不同,地质学家正在使用不同的方法并寻找不同的元素(黄金,煤等),存储这些信息的数据结构需要非常灵活。
答案 0 :(得分:5)
查看NH 3.2的新Mapping By Code功能。它应该可以在运行时轻松创建新的表定义。与Fluent相比,您不需要编写映射类,只需在for循环中添加新类:
// lookup all dynamic tables in the database using SQL or SMO or whatever
var dynamicTables = GetDynamicTables();
// map all dynamic tables
foreach(var table in dynamicTables)
{
mapper.Class<MyGenericEntity>(ca =>
{
// use an entity name to distinguish the mappings.
ca.EntityName(table.Name);
ca.Id(x => x.Id, map =>
{
map.Column("Id");
map.Generator(Generators.HighLow, gmap => gmap.Params(new { max_low = 100 }));
});
// map properties, using what ever is required: if's, for's ...
ca.Property(x => x.Something, map => map.Length(150));
});
}
使用实体名称,您可以在不同的表中存储和加载实体,即使它们被映射为同一个实体类。它就像Duck Typing With NHibernate.。
相信我,这并不容易。如果您对每个NH专家都面临的重大挑战感兴趣,那就去吧。如果你只想让它工作,你应该选择一种更经典的方式:创建一个静态数据库模型,它能够以通用方式存储动态数据(比如:名称值对)。
答案 1 :(得分:4)
请参阅Using nNHibernate with Emitted Code
中的回答class DynamicClass
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Location Location { get; set; }
public virtual IDictionary DynamicData { get; set; }
}
模板
<hibernate-mapping>
<class name="DynamicClass">
...
<dynamic-component name="DynamicData">
<!--placeholder -->
</dynamic-component>
</class>
</hibernate-mapping>
用生成的
替换<!--placeholder -->
<property
name="P1"
type="int" />
<property
name="P2"
type="string" />
配置Sessionfactory
var sessionFactory = new NHibernate.Cfg.Configuration()
.AddXml(generatedXml)
... // DatabaseIntegration and other mappings
.BuildSessionFactory();
查询
var query = session.CreateCriteria<DynamicClass>();
foreach (var restriction in restrictions)
{
query.Add(Restrictions.Eq(restriction.Name, restriction.Value))
}
var objects = query.List<DynamicClass>();
编辑:我还没有意识到每个客户需要多个表
选项1:
带有replace的 <class name="DynamicClass" table="tablenameplaceholder">
和每个动态类的不同Sessionfactory
选项2:
对动态类进行子类化并使用TPS(每个子类的表)映射
选项3:仅使用xml
查看 Stefans 回答 <class name="DynamicTable1" class="DynamicClass" table="DynamicTable1">