NHibernate动态映射

时间:2011-08-24 07:23:57

标签: nhibernate fluent-nhibernate

我正在寻找一些方法来使用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中。

一些背景知识 该应用程序将用于存储地质数据。由于地质数据根据地点而存在固有的不同,地质学家正在使用不同的方法并寻找不同的元素(黄金,煤等),存储这些信息的数据结构需要非常灵活。

2 个答案:

答案 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">