Можно ли отобразить несколько таблиц в модель одного домена с помощью NHibernate? - PullRequest
3 голосов
/ 22 июля 2009

Можно ли отобразить несколько таблиц в модель одного домена с помощью NHibernate? Это в основном UNION , что-то вроде показанного ниже, но я не уверен, как делать модели предметной области в C # и отображениях NHibernate.

У меня в основном 1 абстрактный класс и 2 конкретные классы. Каждый конкретный класс может быть сопоставлен с одной таблицей в базе данных.

Оператор SQL:

SELECT  *
FROM    InCompleOrders

UNION

SELECT  *
FROM    CompleteOrders 

На данный момент я делаю так:

Модели домена C #:

public enum Status
{
  InComplete = 1,
  Pending = 2,
  Complete = 3
}
public abstract class BaseOrder : Entity
{
  public string Property1 {get;set;}
  public string Property2 {get;set;}
  public string Property3 {get;set;}


  public Status Status {get;set;}
  public string Reference {get;set;} //this is unique
}
public class InCompleteOrder : BaseOrder
{
  public override Status Status
  {
    get { return Status.InComplete; }
  }
}
public class Order : BaseOrder
{
  public DateTime DeliveredOn {get;set;}
  public DateTime PaidOn {get;set;}
}

Таблицы базы данных:

InCompleOrders table
  InCompleOrderId INT PK
  Property1 varchar(255) NULL
  Property2 varchar(255) NULL
  Property3 varchar(255) NULL

CompleteOrders table
  CompleteOrderId INT PK
  Status INT
  Property1 varchar(255) NOT NULL
  Property2 varchar(255) NOT NULL
  Property3 varchar(255) NOT NULL
  DeliveredOn datetime NOT NULL
  PaidOn datetime NOT NULL

Отображение NHibernate:

<class name="Order" table="CompleteOrders">
  <id name="Id" column="CompleteOrderId" type="int">
    <generator class ="hilo"></generator>
  </id>
  <property name="DeliveredOn" column="DeliveredOn" not-null="true" type="DateTime" />
  <property name="PaidOn" column="PaidOn" not-null="true" type="DateTime" />

  <property name="Property1" column="Property1" not-null="true" type="string" />
  <property name="Property2" column="Property2" not-null="true" type="string" />
  <property name="Property3" column="Property3" not-null="true" type="string" />
</class>

<class name="InCompleteOrder " table="InCompleOrders">
  <id name="Id" column="InCompleOrderId" type="int">
    <generator class ="hilo"></generator>
  </id>

  <property name="Property1" column="Property1" not-null="false" type="string" />
  <property name="Property2" column="Property2" not-null="false" type="string" />
  <property name="Property3" column="Property3" not-null="false" type="string" />

</class>

Я хочу избегать таких вещей, как:

public BaseOrder GetByReference (string reference)
{
  BaseOrder bo;

  var repoOrder = new Repository<Order>();
  bo = repoOrder.FindOne(query); 
  //query = Restrictions.Eq("Reference", reference)

  if (bo == null)
  {
    var repoInCompOrder = new Repository<InCompleteOrder>();
    bo = repoInCompOrder.FindOne(query); 
    //query = Restrictions.Eq("Reference", reference)
  }

  return bo;
}

И я хочу иметь возможность делать такие вещи, как:

public Order GetByReference (string reference)
{
  var repoOrder = new Repository<Order>();
  var bo = repoOrder.FindOne(query); 
  //query = Restrictions.Eq("Reference", reference) //reference = "abc"
  //and this will generate a SQL similar to:
  //
  //SELECT CompleteOrderId
  //       , Status 
  //FROM   CompleteOrders 
  //WHERE  Reference = 'abc'
  //
  //UNION
  //
  //SELECT InCompleOrderId 
  //       , 1 AS 'Status'
  //FROM   InCompleOrders 
  //WHERE  Reference = 'abc'

  return bo;
}

Ответы [ 2 ]

4 голосов
/ 24 июля 2009

Да, есть ряд опций, которые вы можете использовать, чтобы делать то, что вы хотите. У Айенде Рахиен есть отличная демонстрация параметров для наследования таблиц и полученных в результате структур таблиц.

Используя иерархию классов, которая имеет абстрактный BaseOrder в качестве родителя для CompleteOrder и IncompleteOrder, регистр объединения:

<class name="CompleteOrder" table="CompleteOrders">
    <id name="Id">
        <generator class="identity"/>
    </id>
    <property name="Status"/>
</class>

<class name="IncompleteOrder" table="IncompleteOrders">
    <id name="Id">
        <generator class="identity"/>
    </id>
</class>

или

 <class name="BaseOrder" abstract="true" table="Orders">
    <id name="Id">
        <generator class="hilo"/>
    </id>

    <union-subclass table="CompleteOrders" name="CompleteOrder">
        <property name="Status"/>
    </union-subclass>

    <union-subclass table="IncompleteOrders" name="IncompleteOrder">
    </union-subclass>
</class>

, которая также имеет отдельные таблицы, но не использует объединение для запроса.

Ознакомьтесь с статьей , это, вероятно, очень поможет.


редактирование:

Был комментарий о том, что я не хочу сниматься, но его больше нет. Я не уверен, был ли он удален или это была ТАКАЯ проблема ...

Если BaseOrder.Status является виртуальным свойством, вы должны иметь возможность передавать BaseOrder и не нуждаетесь в приведении. Вам придется поддерживать дополнительную иерархию классов, но вы все равно можете запрашивать их вместе, и, по большей части, остальная часть приложения не должна знать о подклассах.

Удачи!

0 голосов
/ 24 июля 2009

Рассматривали ли вы использование [view][1]?

Вы можете определить свой view следующим образом:

CREATE VIEW AllOrders AS
  SELECT CompleteOrderId
         , Status 
  FROM   CompleteOrders 
  WHERE  Reference = 'abc'

  UNION

  SELECT InCompleOrderId 
         , 1 AS 'Status'
  FROM   InCompleOrders 
  WHERE  Reference = 'abc'

С точки зрения Hibernate (и, вероятно, NHibernate), AllOrders - это просто еще одна таблица для сопоставления вашего доменного объекта.

Одно предупреждение: вы не сможете выполнять вставки в представление (обновления могут работать, а могут и не работать, я не уверен). Поэтому, если вам нужно выполнить операции записи, вам все равно может потребоваться сопоставить данные с CompleteOrders и InCompleteOrders независимо.

Редактировать: похоже, я ошибся из-за невозможности вставить данные в представления - http://www.google.com/search?q=insertable%20view

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