NHibernate динамическое отображение - PullRequest
6 голосов
/ 24 августа 2011

Я ищу способ динамического сопоставления классов таблиц базы данных в моем приложении с помощью nhibernate (или, если работает какой-то другой ORM, дайте мне знать). Я довольно новичок в nhibernate, хотя в прошлом я использовал структуры сущностей.

Большая часть моего приложения будет использовать статические структуры и свободный nhibernate для их отображения.

Однако существует несколько таблиц базы данных, которые необходимо будет создать и сопоставить с объектами на каждом сайте установки. Все они будут иметь базовую структуру (идентификатор, имя и т. Д.), Однако у них будут дополнительные поля в зависимости от типа данных, которые они собирают. Из некоторого прочтения я обнаружил, что могу использовать отображение «dynamic-component» в xml для добавления полей с помощью свойства IDictionary Attributes. Это первый шаг и кажется относительно простым. Ссылка (http://ayende.com/blog/3942/nhibernate-mapping-dynamic-component)

Второй шаг - это то, где я борюсь. Мне нужно будет определить таблицы и отобразить их в зависимости от потребностей клиента. Как указано выше, каждая из таблиц будет иметь набор статических свойств и некоторые динамические. Они также должны будут ссылаться на статический класс «Location», как показано ниже

Местоположение (STATIC) (id, координаты)
----- DynamicTable1 (DYNAMIC) (идентификатор, имя, location_id, DynamicAttribute1, DynamicAttribute2 ........)
----- DynamicTable2 (DYNAMIC) (идентификатор, имя, location_id, DynamicAttributeA, DynamicAttributeB ....)

Нам нужно будет создать / отобразить столько динамических таблиц, сколько необходимо клиенту. DynamicTable1, DynamicTable2 и т. Д., Скорее всего, будут отличаться в некоторых отношениях для большинства клиентских сайтов. Есть ли способ в nhibernate добиться этого? Создание / управление таблицами в базе данных будет осуществляться в другом месте, мне просто нужен какой-то способ, чтобы отобразить это в моем ORM.

немного фона
Это приложение будет использоваться для хранения геологических данных. Поскольку геологические данные по своей сути различаются в зависимости от того, где они находятся, а геолог использует разные методы и ищет разные элементы (золото, уголь и т. Д.), Структура данных для хранения этой информации должна быть чрезвычайно гибкой.

Ответы [ 2 ]

5 голосов
/ 25 августа 2011

Взгляните на новые функции Mapping By Code NH 3.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));
  });
}

Используя имя объекта, вы можете сохранять и загружать объекты в разные таблицы, даже если они отображаются как один и тот же класс объектов. Это похоже на Duck Typing с NHibernate. .

Поверь мне, это будет нелегко. Если вы заинтересованы в большом испытании, которое впечатляет каждого специалиста по NH, просто сделайте это. Если вы просто хотите, чтобы это работало, вам следует выбрать более классический способ: создать статическую модель базы данных, которая способна хранить динамические данные в общем виде (скажем, пары имя-значение).

4 голосов
/ 25 августа 2011

см. Ответ в Использование nNHibernate с излучаемым кодом

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; }
}

Template

<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>();

Редактировать: ups я не понял, что вам нужно несколько таблиц на клиента

Вариант 1:

<class name="DynamicClass" table="tablenameplaceholder"> с заменой и другой Sessionfactory для каждого динамического класса

Вариант 2:

Создание подклассов динамического класса и использование отображений TPS (таблица на подкласс)

Вариант 3: см. Стефанс ответ только с xml

<class name="DynamicTable1" class="DynamicClass" table="DynamicTable1">

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...