是否可以使用 NHibernate 将多个表映射到单个域模型?
是否可以使用 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;
}
Is it possible to map multiple tables to a single domain model using NHibernate? It's basically a UNION, something like shown below but I am not sure how to do the domain models in C# and mappings of NHibernate.
I basically have 1 abstract class and 2 concrete classes. Each concrete class can be mapped to a single table in the databse.
SQL statement:
SELECT *
FROM InCompleOrders
UNION
SELECT *
FROM CompleteOrders
At the moment I am doing like this:
C# domain models:
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;}
}
Database tables:
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 mapping:
<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>
I want to avoid doing things like:
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;
}
And I want to be able to do things like:
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您可以使用多种选项来完成您想要的操作。 Ayende Rahien 有一个关于选项的精彩演示< /a> 用于表继承和生成的表结构。
使用具有抽象 BaseOrder 作为 CompleteOrder 和 IncompleteOrder 父级的类层次结构,联合情况为:
或者
也具有单独的表,但不使用联合进行查询。
查看文章,它可能会有很大帮助。
编辑:
有一条关于不想投射的评论,但现在已经消失了。 我不确定它是否被删除或者是否是一个 SO 问题...
如果 BaseOrder.Status 是虚拟属性,您应该能够传递 BaseOrder 而不需要进行强制转换。 您必须维护额外的类层次结构,但您仍然可以一起查询它们,并且在大多数情况下,应用程序的其余部分不需要了解子类。
祝你好运!
Yes, there are a number of options you can use to do what you want. Ayende Rahien has a great demonstration of the options for table inheritance and the resulting table structures.
Using the class hierarchy that has an abstract BaseOrder as a parent to CompleteOrder and IncompleteOrder, the union case is:
or
which also has separate tables but doesn't use a union for the query.
Check out the article, it will probably help greatly.
edit:
There was a comment about not wanting to cast but it's now gone. I'm not sure if it was deleted or if it was a SO issue...
If BaseOrder.Status is a virtual property, you should be able to pass around a BaseOrder and not need to cast. You'll have to maintain the extra class hierarchy but you can still query them together and, for the most part, the rest of the application shouldn't need to know about the subclasses.
Good luck!
您是否考虑过使用
[view][1]
?您可以按如下方式定义您的
view
:从 Hibernate(大概还有 NHibernate)的角度来看,
AllOrders
只是将域对象映射到的另一个表。需要注意的是,您将无法对视图执行插入(更新可能有效,也可能无效,我不确定)。 所以如果需要执行写操作,可能仍然需要独立映射到CompleteOrders和InCompleteOrders。
编辑:看来我错误地认为无法将数据插入视图 - http:// /www.google.com/search?q=insertable%20view
Have you considered using a
[view][1]
?You can define your
view
as follows:From Hibernate's (and presumably NHibernate's) point of view,
AllOrders
is just another table to map your domain object to.One caveat is that you will not be able to perform inserts to the view (updates may or may not work, I'm not sure). So if you need to perform write operations, you may still need to map to CompleteOrders and InCompleteOrders independently.
Edit: Looks like I was mistaken about not being able to insert data into views - http://www.google.com/search?q=insertable%20view