• 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

  • 相关阅读:
    素数筛法
    UVA, 967 Circular
    软件开发一些常用工具
    iOS 一些常用方法笔记
    iOS 项目调试
    UINavigation的基本使用
    Tomcat多实例部署
    五联疫苗介绍
    互联网公司架构
    分布式事务
  • 原文地址:https://www.cnblogs.com/jams742003/p/1622389.html
Copyright © 2020-2023  润新知