NHibernate动态映射

NHibernate动态映射,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,我正在寻找使用nhibernate在我的应用程序中动态映射数据库表类的方法(或者如果其他ORM可以工作,请告诉我)。我是nhibernate的新手,但我过去使用过实体框架 我的大部分应用程序将使用静态结构和fluent nhibernate来映射它们 但是,需要创建多个数据库表,并将其映射到每个安装站点上的对象。这些字段都将作为基本结构(id、名称等),但是根据所捕获的数据类型,它们将具有附加字段。通过一些阅读,我发现我可以使用xml中的“动态组件”映射来添加使用IDictionary属性的字段

我正在寻找使用nhibernate在我的应用程序中动态映射数据库表类的方法(或者如果其他ORM可以工作,请告诉我)。我是nhibernate的新手,但我过去使用过实体框架

我的大部分应用程序将使用静态结构和fluent nhibernate来映射它们

但是,需要创建多个数据库表,并将其映射到每个安装站点上的对象。这些字段都将作为基本结构(id、名称等),但是根据所捕获的数据类型,它们将具有附加字段。通过一些阅读,我发现我可以使用xml中的“动态组件”映射来添加使用IDictionary属性的字段。这是第一步,看起来比较直截了当。参考号(http://ayende.com/blog/3942/nhibernate-mapping-dynamic-component)

第二步是我挣扎的地方。我需要根据客户的需要定义表并映射它们。如上所述,每个表都有一组静态属性和一些动态属性。他们还需要引用一个静态的“Location”类,如下所示

位置(静态)(id、坐标)
-----DynamicTable1(动态)(id、名称、位置\u id、DynamicAttribute 1、DynamicAttribute 2……)
-----DynamicTable2(动态)(id、名称、位置\u id、DynamicAttributeA、DynamicAttributeB….)

我们需要能够根据客户需要创建/映射尽可能多的这些动态文件。对于大多数客户端站点,DynamicTable1、DynamicTable2等很可能在某些方面有所不同。nhibernate有什么方法可以实现这一点吗?数据库中表的创建/管理将在其他地方进行管理,我只需要某种方法将其映射到我的ORM中

一点背景知识
此应用程序将用于存储地质数据。由于地质数据在不同的位置有着本质的不同,地质学家使用不同的方法寻找不同的元素(黄金、煤炭等),因此存储这些信息的数据结构需要非常灵活。

请参见中的答案

模板

<hibernate-mapping>
  <class name="DynamicClass">
    ...
    <dynamic-component name="DynamicData">
      <!--placeholder -->
    </dynamic-component>
  </class>
</hibernate-mapping>
质疑

var query=session.CreateCriteria();
foreach(限制中的var限制)
{
query.Add(Restrictions.Eq(restriction.Name,restriction.Value))
}
var objects=query.List();
编辑:我没有意识到每个客户需要多张表

备选案文1:

带有替换和每个动态类的不同Sessionfactory

备选案文2:

子类化动态类并使用TPS(每个子类的表)映射

选项3:请参见Stefans仅用xml回答

查看NH3.2的新功能。它应该使在运行时创建新的表定义变得容易。与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));
  });
}
//使用SQL或SMO或其他工具查找数据库中的所有动态表
var dynamicTables=GetDynamicTables();
//映射所有动态表
foreach(dynamicTables中的var表)
{
类(ca=>
{
//使用实体名称来区分映射。
ca.EntityName(表名);
ca.Id(x=>x.Id,map=>
{
地图栏(“Id”);
生成器(Generators.HighLow,gmap=>gmap.Params(new{max_low=100}));
});
//映射属性,使用所需的内容:if's,for's。。。
属性(x=>x.Something,map=>map.Length(150));
});
}
使用实体名称,您可以在不同的表中存储和加载实体,即使它们映射为相同的实体类。就像是


相信我,这并不容易。如果你对一个给每个NH专家留下深刻印象的大挑战感兴趣,就去做吧。如果你只是想让它工作,你应该选择一种更经典的方式:创建一个静态数据库模型,它能够以一种通用的方式(比如:名称-值对)存储动态数据。

我不知道你是否可以针对每个站点上数据库结构的差异做些什么。在我看来,最好是将动态数据存储在灵活、通用但静态的结构中,因为有不同的数据库。这可能有助于Hi Firo
这正是我想对问题的动态列部分所做的。我仍然不知道如何动态添加表,尽管我正在尝试使用这种方法,但我正在努力使会话工厂正常工作。。。这是否使用流畅。配置?您可以将sessionfactory代码扩展为完整的代码吗?@PaulGrimshaw提供的代码不使用FluentNHibernate,但您可以流利地使用
。我已经编辑了代码,但是没有太多需要添加的内容,谢谢你的帖子。我真的开始明白我想要在这里实现的目标可能有点太难了。如果我得到一些灵感,我会更新,否则现在就尝试静态结构。FluentNHibernate也可以这样做。不要使用
mapper.Class()
只需使用
var-map=new-ClassMap();map.Id(x=>x.Id);模型。添加(地图)
。然而,代码映射是绑定到类的,类上不存在的属性是不可映射的,不像FluentNH和hbm可以映射;有没有办法撤销这些映射(使它们真正动态化)?比方说,如果我有一个“main”映射到一个表,并且想在一个场景中使用另一个映射,那么就返回到“main”。
<property
  name="P1"
  type="int" />
<property
  name="P2"
  type="string" />
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>();
// 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));
  });
}