1. 程式人生 > 實用技巧 >NHibernate之(8):巧用元件之依賴物件

NHibernate之(8):巧用元件之依賴物件

本節內容

  • 引入
  • 方案1:直接新增
  • 方案2:巧用元件
  • 例項分析
  • 結語

    返回文章列表

引入

通過前面7篇的學習,有點乏味了~~~這篇來學習一個技巧,大家一起想想如果我要在Customer類中實現一個Fullname屬性(就是Firstname和Lastname的組合)該怎麼做呢?

方案1:直接新增

“我知道!修改Customer類,新增一個Fullname屬性!即Customer.Fullname!”

“恩,完全正確......”

“這就意味著在Customer類中把Firstname和Lastname兩個屬性重新修改組合為Fullname屬性。這樣的話,如果有其它的類(像Vendor、Shiper)使用了Firstname和Lastname兩個屬性,這就需要修改很多業務邏輯。那你的麻煩可就大了,還有什麼方法嗎?”

“.........”

方案2:巧用元件

NHibernate中,提供了元件(Component)和動態元件來幫助我們完成這件事情。其實元件在NHibernate中為了不同目的被重複使用。這裡我們使用它來依賴物件

對映檔案中,<component>元素把子物件的一些屬性對映為父類對應的表的一些欄位。然後,元件可以定義它們自己的屬性、元件或者集合。

下面用兩幅圖顯示元件和動態元件兩個節點對映屬性:

看看這些對映屬性:

  • access(預設property):NHibernate用來訪問屬性的策略
  • class(預設通過反射得到的屬性型別):元件(子)類的名字
  • insert:被對映的欄位是否出現在SQL的INSERT語句中
  • name:屬性名propertyName
  • update:被對映的欄位是否出現在SQL的UPDATE語句中
  • <property>子元素:為元件(子)類的一些屬性與表字段之間建立對映
  • <parent>子元素:在元件類內部就可以有一個指向其容器的實體的反向引用

<dynamic-component>元素允許一個IDictionary作為元件對映,其中屬性名對應字典中的鍵。這又是使用元件的另一種用法。

知道上面的知識,我們該想想上面的問題該如何利用元件來實現了吧。

例項分析

我們用一幅圖來展示我們這節所說的一切:

開始動手吧!

1.新建Name類



namespace NHibernateOper.DomainModel
{

    public class Name
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Fullname
        {
            get
            {
                return Firstname + " " + Lastname;
            }
        }
    }
}

簡單的說,這個類用於組合Fullname屬性。

2.新增CustomerComp類

namespace NHibernateOper.DomainModel
{
    public class CustomerComp
    {
        public virtual int CustomerId { get; set; }
        //版本控制
        public virtual int Version { get; set; }
        public virtual Name Name { get; set; }
    }
}

修改Customer類,去除原來的Firstname和Lastname屬性,新增Name屬性。這時Name作為Customer的一個組成部分。需要注意的是:和原來Firstname和Lastname屬性一樣,需要對Name的持久化屬性定義getter和setter方法,但不需要實現任何的介面或宣告識別符號欄位。

3.新增CustomerComp對映

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                           assembly="NHibernateOper.DomainModel"
                   namespace="NHibernateOper.DomainModel">
    <class name ="NHibernateOper.DomainModel.CustomerComp,NHibernateOper.DomainModel" table="CustomerComp">
        <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
            <generator class ="native"></generator>
        </id>
        <version name="Version" column="Version" type="Int32" unsaved-value="0"/>
        <component name="Name" class="NHibernateOper.DomainModel.Name,NHibernateOper.DomainModel">
            <property name="Firstname" column ="Firstname" type="string"
                                 length="50" not-null="false" unique-key="UC_CustomerName"/>
            <property name ="Lastname" column="Lastname" type="string"
                                 length="50" not-null="false" unique-key="UC_CustomerName"/>
        </component>
    </class>
</hibernate-mapping>

首先定義Component的一些屬性,指定屬性名和元件對映的類名。再使用<property>子元素,為Name類的Firstname、Lastname屬性與表字段之間建立對映。是不是很簡單~~

這時Customer表中還是CustomerId、Version、Firstname、Lastname欄位。完全不需要修改資料庫表結構哦。

這裡需要注意兩點:

  1. 就像所有的值型別一樣,元件不支援共享引用。元件的值為空從語義學上來講是專有的。每當重新載入一個包含元件的物件,如果元件的所有欄位為空,那麼NHibernate將假定整個元件為空。對於絕大多數目的,這樣假定是沒有問題的。
  2. 元件的屬性可以是NHibernate型別(包括集合、多對一關聯以及其它元件)。巢狀元件不應該作為特殊的應用被考慮。NHibernate趨向於支援設計細粒度的物件模型。

4.編寫方法

這時,我們需要修改或者重新編寫新的方法來實現我們想要的邏輯。

public IList<CustomerComp> ReturnFullName(string firstname, string lastname)
{
    return _session
         .CreateQuery("from CustomerComp c where c.Name.Firstname=:fn and c.Name.Lastname=:ln")
        .SetString("fn", firstname)
        .SetString("ln", lastname)
        .List<CustomerComp>();
}

現在,我們訪問Customer的Firstname、Lastname屬性,只需要在原來的基礎上通過Name訪問,例如上面修改的情況,看看上面圖片上怎麼訪問的吧,一目瞭然。

如果我們要新增一個Customer怎麼辦呢?程式碼片段如下所示:

var customerComp = new CustomerComp() { Name = new Name() { Firstname = "zhang", Lastname = "san" } };

5.測試方法

有了上面的方法,我們編寫一個測試用例測試一下這個方法吧:看看結果測試成功,OK。

[Test]
public void ReturnFullNameTest()
{
    IList<CustomerComp> customers = oper.ReturnFullName("zhang","san");
    foreach (CustomerComp c in customers)
    {
        Assert.AreEqual("zhang san", c.Name.Fullname);
    }
}

結語

這一篇像大家介紹一個使用元件技巧,通過元件可以改善我們的物件模型,而資料庫結構不需要變化。通過這一篇的技巧,利用元件來對映來依賴物件,可以非常連貫的引入NHibernate中的多表對映關係、集合等內容,這些才是NHibernate中的亮點,就連LINQ都比不過它。從下篇開始就來學習NHibernate中的閃光點。

本系列連結:NHibernate之旅系列文章導航

NHibernate Q&A

下次繼續分享NHibernate!