首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

NHibernate實戰(8):組件映射實現依賴對象優化

     編輯:關於.NET

前言

面對「Customer 需 Fullname = Firstname + Lastname」的需求,直接添加屬性會導致模型膨脹與重複。本文演示 NHibernate 組件 功能,實現細粒度對象模型與單表映射的完美結合。

兩種方案對比

  • 方案一:直接添加 Fullname 屬性——破壞封裝,若 Vendor/Shipper 同樣需姓名組合則大量重複代碼
  • 方案二:組件映射——提取 Name 值對象,複用邏輯,資料庫結構零變動

組件映射核心元素

<component> 將子對象屬性映射到父表欄位,支援嵌套組件、集合、關聯。關鍵屬性:

  • name:父類屬性名
  • class:組件類全名
  • insert/update:控制欄位是否參與 INSERT/UPDATE
  • 子元素 <property> 映射組件屬性到表欄位
  • 子元素 <parent> 提供組件到容器的反向引用

<dynamic-component> 則允許 IDictionary 作為組件映射,鍵值對應屬性名。

實戰步驟

1. 定義組件類

namespace DomainModel.Entities
{
    public class Name
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Fullname => Firstname + " " + Lastname;
    }
}

純粹的值對象,無標識符,無需實現介面,封裝格式化邏輯。

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; } // 替代原 Firstname/Lastname
    }
}

注意:組件屬性同樣需要 getter/setter,NHibernate 透過屬性存取實現持久化。

3. 映射文件配置

<class name="DomainModel.Entities.Customer,DomainModel" table="Customer">
    <id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
        <generator class="native" />
    </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"
            unique-key="UC_CustomerName"/>
        <property name="Lastname" column="Lastname" type="string" length="50"
            unique-key="UC_CustomerName"/>
    </component>
</class>

效果:資料表仍為 CustomerId, Version, Firstname, Lastname,零結構變更。

4. 重要特性提醒

  • 值語義:組件不支援共享引用,所有欄位為 null 時視為整體 null
  • 嵌套支援:組件屬性可為集合、多對一、其他組件,鼓勵細粒度建模
  • 查詢訪問:HQL 中通過路徑訪問 c.Name.Firstname

5. 業務代碼適配

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

// 新建
var customer = new Customer 
{ 
    Name = new Name { Firstname = "YJing", Lastname = "Lee" } 
};

6. 測試驗證

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

結語

組件映射實現了對象模型豐富化與資料庫模型簡潔化的雙贏:

  • 業務邏輯封裝在值對象中(如 Name.Fullname)
  • 複用性強:Vendor/Shipper 可共用 Name 組件
  • 零資料庫遷移成本
  • 為後續多表關聯、集合映射鋪平道路

這正是 NHibernate 超越 LINQ to SQL 的建模靈活性所在。下篇進入關係映射核心領域。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved