3

是否可以使用 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;
}
4

2 回答 2

4

是的,您可以使用许多选项来做您想做的事。Ayende Rahien很好地演示了表继承和生成的表结构的选项。

使用具有抽象 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>

它也有单独的表,但不使用联合进行查询。

查看文章,它可能会有很大帮助。


编辑:

有一条评论说不想投,但现在已经消失了。我不确定它是否被删除或者它是否是一个 SO 问题......

如果 BaseOrder.Status 是虚拟属性,您应该能够传递 BaseOrder 而无需强制转换。您必须维护额外的类层次结构,但您仍然可以一起查询它们,并且在大多数情况下,应用程序的其余部分不需要了解子类。

祝你好运!

于 2009-07-24T02:19:39.157 回答
-1

您是否考虑过使用[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

于 2009-07-24T02:09:45.270 回答