两个数据表
Customer,客户表,现有数据如下:
--------------------------------------------------------------
CustomerId Version FirstName LastName
1 2 Jimmy1 Clonee
--------------------------------------------------------------
Version现在不用。客户表中一条记录,Jimmy1·Clonee用户
Order,订单表,现有数据如下:
--------------------------------------------------------------
orderid version orderdate customer memo
1 NULL
2 NULL
3 NULL
--------------------------------------------------------------
现有3条记录,且3条记录全是Jimmy1用户的订单
数据库表名及字段名是大小写不敏感的,但做为Mapping来说,是严格的(敏感的),这点很容易理解。
(一)持久类
(1)一对多关系中的“一”方
public class Customer
{
public virtual int Unid { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual ISet<Order> Orders { get; set; }
}
说明一下:客户持久实体Customer,除了3个常规的字段外(数据库表Customer表的字段),还有一个Orders属性。它代表的意思是客户的所有订单。
(2)一对多关系中的“多”方
public class Order
{
public virtual int Unid { get; set; }
public virtual DateTime OrderDate { get; set; }
public virtual string Memo { get; set; }
public virtual Customer Customer { get; set; }
}
说明一下:订单持久实体Order,除了3个常规字段外(数据库表Order表的字段),还有一个Customer属性,此属性持久为Customer 类型,其实与数据库两表一对多关系中的链结点(外键,order表的customer字段)是有关系的。这种关系很微妙,我解释不清。表中为整型,但这里却持久为对象。
(二)映射
(1)客户表映射
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Entities">
<class name="Customer" table="customer">
<id name="Unid" column="customerid">
<generator class="native"></generator>
</id>
<property name="FirstName" column="firstname"></property>
<property name="LastName" column="lastname"></property>
<!--一对多关系:Customer有一个或多个Orders-->
<set name="Orders" table="Order" generic="true" inverse="true">
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
常规属性与单表映射没有太大区别,改动的地方就是多出来的那个集合属性,也就是描述(或说持久)“多”关系表的属性。
·属性{ ISet<Order> Orders }由set来映射,对应的表名为Order,这里有点不明白,为么这个Order不用添加’order’或[order]。
·key属性,对应order表中的customer字段(其实如果叫customerId会更好);外键名称:FK_CustomerOrders
·一对多关系中的类Order(这个是持久类Order)
(2)订单表映射
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Entities">
<class name="Domain.Entities.Order,Domain" table="[Order]" >
<id name="Unid" column="OrderId" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="OrderDate" column="OrderDate" type="DateTime" not-null="true" />
<property name="Memo" column="Memo" type="String"/>
<!--多对一关系:Orders属于一个Customer-->
<many-to-one name="Customer" column="Customer" not-null="true" class="Customer" foreign-key="FK_CustomerOrders"/>
</class>
</hibernate-mapping>
订单表映射常规属性与单表映射也没有太大区别。作为一对多关系中的多的一方,只需定义:
·多对一 名称Customer,对应于持久类Order中的Customer属性(类型为Customer类类型)
·列表(对应数据库表order的customer字段(其实用customerId更好))
·类名,Customer
·外键:CustomerOrders
提示:这里有点要注意,那就是:因为订单表order与sql关键字相同,所以进行操作时,我们应该添加[order],nhibernate文档中要用到单引号,但可能由于版本原因还是其它原因,这里只能使用中括号。
<class name="Domain.Entities.Order,Domain" table="[Order]" >
所以这里要注意一下,最好是建表和字段时,避免此类情况。(可能影响释义性)
(三)取得客户
public IList<Customer> ShowListCustomerOrders()
{
return _session.CreateQuery("select c from Customer c inner join c.Orders o")
.List<Customer>();
}
(四)测试
public void TestMany()
{
IList<Customer> _list = hh.ShowListCustomerOrders();
Console.WriteLine(_list[0].LastName);
ISet<Order> ss = _list[0].Orders;
foreach (Order oo in ss)
Console.WriteLine(oo.OrderDate);
}
结果:
Clonee
1台电视
2台冰箱
10本书
(五)补充说明
对于多的一方,当前所用集合类型为 Iset泛型。
引用Lee的一段解释:
Bag:对象集合,每个元素可以重复。在.Net中相当于IList或者IList<T>实现。
Set:对象集合,每个元素必须唯一。在.Net中相当于ISet或者ISet<T>实现,Iesi.Collections.dll程序集提供ISet集合。
List:整数索引对象集合,每个元素可以重复。在.Net中相当于ArraryList或者List<T>实现。
Map:键值对集合。在.Net中相当于HashTable或者IDictionary<Tkey,TValue>实现
关于ISet这个不重复特性(须唯一),不太理解。
现在用常规的Bag(IList)来试一下。
(1) 更改Customer持久类的Orders属性
public virtual IList<Order> Orders { get; set; }
(2) 更改映射文件
<bag name="Orders" table="order" generic="true" inverse="true">
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Order"/>
</bag>
(3) 测试结果与Iset相同
更多内容请见:http://www.cnblogs.com/lyj/archive/