程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> NHibernate之旅(8):巧用組件之依賴對象

NHibernate之旅(8):巧用組件之依賴對象

編輯:關於.NET

本節內容

引入

方案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 DomainModel.Entities
{
  public class Name
  {
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Fullname
    {
      get
      {
        return Firstname + " " + Lastname;
      }
    }
  }
}

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

2.修改Customer類

namespace DomainModel.Entities
{
  public class Customer
  {
    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.修改Customer映射

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
              assembly="DomainModel" namespace="DomainModel">
 <class name ="DomainModel.Entities.Customer,DomainModel" table="Customer">
  <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
   <generator class ="native"></generator>
  </id>
  <version name="Version" column="Version" type="integer" unsaved-value="0"/>
  <component name="Name" class="DomainModel.Entities.Name,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字段。完全不需要修改數據庫表結構哦。

這裡需要注意兩點:

就像所有的值類型一樣,組件不支持共享引用。組件的值為空從語義學上來講是專有的。每當重新加載一個包含組件的對象,如果組件的所有字段為空,那麼NHibernate將假定整個組件為空。對於絕大多數目的,這樣假定是沒有問題的。

組件的屬性可以是NHibernate類型(包括集合、多對一關聯以及其它組件)。嵌套組件不應該作為特殊的應用被考慮。NHibernate趨向於支持設計細粒度的對象模型。

4.編寫方法

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

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

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

如果我們要添加一個Customer怎麼辦呢?代碼片段如下所示:

var customer = new Customer() { Name = new Name() { Firstname = "YJing", Lastname = "Lee" } };5.測試方法

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

[Test]
public void ReturnFullNameTest()
{
  IList<Customer> customers = _relation.ReturnFullName("YJing","Lee");
  foreach (Customer c in customers)
  {
    Assert.AreEqual("YJing Lee", c.Name.Fullname);
  }
}

結語

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved