NHibernate初探(四) 一对多关系测试示例

两个数据表

Customer,客户表,现有数据如下:

 

--------------------------------------------------------------

CustomerId  Version FirstName   LastName

1           2       Jimmy1      Clonee

--------------------------------------------------------------

 

Version现在不用。客户表中一条记录,Jimmy1·Clonee用户

 

Order,订单表,现有数据如下:

 

--------------------------------------------------------------

orderid version orderdate   customer    memo

1   NULL    2009-11-09 16:54:41.013 1   1台电视

2   NULL    2009-12-12 10:29:00.543 1   2台冰箱

3   NULL    2009-12-12 10:29:01.373 1   10本书

--------------------------------------------------------------

 

现有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类类型)

·列表(对应数据库表ordercustomer字段(其实用customerId更好))

·类名,Customer

·外键:CustomerOrders

 

提示:这里有点要注意,那就是:因为订单表ordersql关键字相同,所以进行操作时,我们应该添加[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这个不重复特性(须唯一),不太理解。

现在用常规的BagIList)来试一下。

 

(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/2008/10/30/1323099.html

原文地址:https://www.cnblogs.com/jams742003/p/1622389.html