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

NHibernate 一對多主從表映射配置實戰指南

     編輯:關於.NET

前言

在實際開發中,主從表關係隨處可見:訂單與明細、班級與學生、部門與員工等。這類「一筆主表記錄對應多筆從表記錄」的一對多關係,是 NHibernate 映射配置的核心場景之一。本文透過班級與學生的經典範例,詳細說明雙向一對多的映射配置與操作技巧。

開發環境

  • Visual Studio 2008 SP1
  • NHibernate 2.1.2.GA

資料庫結構

兩張核心表:

  • Class 表(主表):ClassId (PK)、ClassCode、PeopleCount
  • Student 表(從表):StudentID (PK)、Name、Tel、ClassId (FK)

外鍵關係:Class.ClassId ↔ Student.ClassId

映射檔案配置

主表 Class.hbm.xml - 一對多配置

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model" namespace="NHibernateSample.Model">
  <class name="NHibernateSample.Model.Class, Model" table="`Class`">
    <id name="Id" type="Int32" unsaved-value="0">
      <column name="ClassId" length="4" sql-type="int" not-null="true" unique="true" index="PK_Class"/>
      <generator class="native" />
    </id>
    <property name="ClassCode" type="String">
      <column name="ClassCode" length="50" sql-type="varchar" not-null="false"/>
    </property>
    <property name="PeopleCount" type="Int32">
      <column name="PeopleCount" length="4" sql-type="int" not-null="false"/>
    </property>
    
    <!-- 一對多關聯核心配置 -->
    <bag name="Students" inverse="true" lazy="true" cascade="all-delete-orphan">
      <key column="ClassId"/>
      <one-to-many class="NHibernateSample.Model.Student, Model"/>
    </bag>
  </class>
</hibernate-mapping>

關鍵屬性解析

屬性值說明
nameStudents實體類別中的集合屬性名稱
inversetrue關鍵:由「多」的一方(Student)維護關聯關係,避免重複更新外鍵
lazytrue啟用延遲載入,存取集合時才查詢資料庫
cascadeall-delete-orphan級聯操作:儲存/更新/刪除主表時自動處理從表記錄;孤兒刪除確保無關聯的從表資料被清除

從表 Student.hbm.xml - 多對一配置

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model" namespace="NHibernateSample.Model">
  <class name="NHibernateSample.Model.Student, Model" table="Student">
    <id name="Id" type="Int32" unsaved-value="0">
      <column name="StudentID" length="4" sql-type="int" not-null="true" unique="true" index="PK_Student"/>
      <generator class="native" />
    </id>
    <property name="Name" type="String">
      <column name="Name" length="50" sql-type="varchar" not-null="false"/>
    </property>
    <property name="Tel" type="String">
      <column name="Tel" length="50" sql-type="varchar" not-null="false"/>
    </property>
    
    <!-- 多對一關聯配置 -->
    <many-to-one name="Class" class="NHibernateSample.Model.Class, Model">
      <column name="ClassId" length="4" sql-type="int" not-null="false"/>
    </many-to-one>
  </class>
</hibernate-mapping>

many-to-one 關鍵點

  • name="Class":Student 實體中參考 Class 的屬性名稱
  • class:關聯實體的完整類型名稱
  • column="ClassId":本表中作為外鍵的欄位名稱

實體類別設計要點

// Class 實體(主表)
public class Class
{
    public virtual int Id { get; set; }
    public virtual string ClassCode { get; set; }
    public virtual int PeopleCount { get; set; }
    
    // 集合屬性對應 bag name="Students"
    public virtual IList Students { get; set; } = new ArrayList();
}

// Student 實體(從表)
public class Student
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Tel { get; set; }
    
    // 參考屬性對應 many-to-one name="Class"
    public virtual Class Class { get; set; }
}

新增操作實作

// 建立主從關聯物件
Class c = new Class();
Student stu = new Student();

stu.Name = "tao";
stu.Tel = "123123123";
stu.Class = c;           // 關鍵:從表設定主表參考

c.PeopleCount = 30;
c.ClassCode = "03510236";
c.Students.Add(stu);     // 關鍵:主表集合加入從表物件

// 持久化:只需儲存主表,透過 cascade 自動處理從表
ClassBLL cBLL = new ClassBLL();
cBLL.AddClass(c);

操作核心邏輯:

  1. 建立主表與從表實體
  2. 從表設定主表參考(stu.Class = c)
  3. 主表集合加入從表(c.Students.Add(stu))
  4. 僅儲存主表,cascade 自動級聯儲存從表

常見陷阱與最佳實踐

1. inverse="true" 的重要性

若主表設定 inverse="false"(預設),NHibernate 會由主表維護關聯,導致執行兩次 UPDATE:一次 INSERT 學生,一次 UPDATE 學生的 ClassId。設為 true 後,由 Student 端維護,僅執行一次 INSERT 即含外鍵值。

2. cascade 設定策略

  • all-delete-orphan:適合「從表生命週期完全依附主表」的場景(如訂單明細)
  • save-update:僅級聯新增/更新,刪除主表不刪除從表
  • none:完全手動管理,適用於從表可獨立存在的場景

3. 雙向關聯的一致性

程式碼中務必同時維護兩端:

// 正確做法
student.Class = classObj;
classObj.Students.Add(student);

// 錯誤做法:只設定單向
student.Class = classObj;  // 缺少 classObj.Students.Add(student)

總結

NHibernate 一對多映射的關鍵在於:

  1. 雙向配置:主表用 <bag> + <one-to-many>,從表用 <many-to-one>
  2. 關聯維護權:inverse="true" 交給從表維護,效能更佳
  3. 級聯策略:根據業務需求選擇適當的 cascade 選項
  4. 操作模式:從表設定主表參考 + 主表集合加入從表 = 完成關聯建立

掌握這些核心概念,主從表操作就能得心應手。希望本文對您的 NHibernate 學習之路有所助益!

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