程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 我的NHibernate之路(3)---表間多對多配置篇

我的NHibernate之路(3)---表間多對多配置篇

編輯:關於.NET

本節要點:

1、如何配置表之間多對多的關系

2、多表之間如何進行操作

對於關系型數據庫,表之間也多對多的關系也很常見的。在我們實際開發過 程中如何進行正確的映射的配置,以及所關聯的表之間是如何操作的?這是本文 講述的重點。

開發環境:VS2008 SP1  使用的NHibernate版本:NHibernate-2.1.2.GA- bin。

將上節討論的學生表與班級表再進行深層次的引入:如果構建一個學生選課 的數據庫,還需要什麼表?表之間的關系如何對應?還是通過LINQ的截圖說說表 的字段以及表之間的關系【不討論LINQ與Nhibernate之間的關系,免得又有朋友 誤解】。圖如下:

通過圖,可以很清楚的看出四張表見的關系。不過我主要說的是下面三張表 。

對於學生來說,他可以選擇多門課程。對於課程來說,多個學生也可以選擇 同一門課程。對於學生實體類和課程實體類,他們之間就是一種多對多的關系。 順便給出下面三張表之間的外鍵。students表與SelectCourse:引用列【ID】與 被引用列【Students】,外鍵名:FK_SelectCourse_Students。Course表與 SelectCourse表:引用列【ID】與被引用列【CourseID】,外鍵名: FK_SelectCourse_Course。被引用類那麼他們之間的映射關系如何?

通過上節的說明,一對多是在映射文件中通過one-to-many表示的。大家很自 然想到多對多就是通過many-to-many來表示。有了一對多配置的基礎,我就說說 其中重要的。

Stuents表的映射文件:

 1 <?xml version="1.0" encoding="utf-8" ?>
  2  <hibernate-mapping xmlns="urn:nhibernate-mapping- 2.2" assembly="Model" namespace="NHibernateSample.Model">
  3   <class name="NHibernateSample.Model.Student, Model"  table="Students">
  4     <id name="Id" type="Int32" unsaved- value="0">
  5       <column name="ID" length="4" sql-type="int"  not-null="true" unique="true" index="PK_Students"/>
  6       <generator class="native" />
  7     </id>
  8     <property name="Name" type="String">
  9       <column name="Name" length="50" sql- type="varchar" not-null="false"/>
10     </property>
11     <property name="Phone" type="String">
12       <column name="Phone" length="15" sql- type="varchar" not-null="false"/>
13     </property>
14
15     <many-to-one name="Class"  class="NHibernateSample.Model.Class, Model">
16       <column name="ClassID" length="4" sql- type="int" not-null="false"/>
17     </many-to-one>
18   <bag name="Courses" generic="true"  table="SelectCourse">
19    <key column="StudentID" foreign- key="FK_SelectCourse_Students">
20    </key>
21    <many-to-many column="CourseID" foreign- key="FK_SelectCourse_Course" 
       class="NHibernateSample.Model.Course, Model"  ></many-to-many>
22   </bag>
23   </class>
24  </hibernate-mapping>

Students對應的實體類:

代碼

using System;
using System.Collections;
namespace NHibernateSample.Model
{
   #region Student
   /// <summary>
   /// Student object for NHibernate mapped table  'Students'.
   /// </summary>
   public class Student
   {
     #region Member Variables
     protected int _id;
     protected string _name;
     protected string _phone;
     //多個學生屬於一個班級
     protected Class _class;
     protected IList _Course;
     #endregion
     #region Constructors
     public Student() { }
     public Student( string name, string phone, Class  classes )
     {
       this._name = name;
       this._phone = phone;
       this._class = classes;
     }
     #endregion
     #region Public Properties
     public virtual int Id
     {
       get {return _id;}
       set {_id = value;}
     }
     public virtual string Name
     {
       get { return _name; }
       set
       {
         if ( value != null && value.Length  > 50)
           throw new ArgumentOutOfRangeException ("Invalid value for Name", value, value.ToString());
         _name = value;
       }
     }
     public virtual string Phone
     {
       get { return _phone; }
       set
       {
         if ( value != null && value.Length  > 15)
           throw new ArgumentOutOfRangeException ("Invalid value for Phone", value, value.ToString());
         _phone = value;
       }
     }
     public virtual Class Class
     {
       get { return _class; }
       set { _class = value; }
     }
     public virtual IList Courses
     {
       get
       {
         if (_Course == null)
         {
           _Course = new ArrayList();
         }
         return _Course;
       }
       set { _Course = value; }
     }

     #endregion
   }
   #endregion
}

Course表對應的映射文件:

 1 <?xml version="1.0" encoding="utf-8" ?>
  2  <hibernate-mapping xmlns="urn:nhibernate-mapping- 2.2" assembly="Model"
  3    namespace="NHibernateSample.Model">
  4   <class name="NHibernateSample.Model.Course, Model"  table="Course">
  5     <id name="Id" type="Int32" unsaved- value="0">
  6       <column name="ID" length="4" sql-type="int"  not-null="true" unique="true"
        index="PK_Course"/>
  7       <generator class="native" />
  8     </id>
  9     <property name="CourseName" type="String">
10       <column name="CourseName" length="50" sql- type="varchar" not-null="false"/>
11     </property>
12     <property name="Teacher" type="String">
13       <column name="Teacher" length="50" sql- type="varchar" not-null="false"/>
14     </property>
15     <property name="Time" type="DateTime">
16       <column name="`Time`" length="8" sql- type="datetime" not-null="false"/>
17     </property>
18     <property name="Address" type="String">
19       <column name="Address" length="50" sql- type="varchar" not-null="false"/>
20     </property>
21   <bag name="Students" generic="true"  table="SelectCourse">
22    <key column="CourseID" foreign- key="FK_SelectCourse_Course"/>
23    <many-to-many column="StudentID"  class="NHibernateSample.Model.Student, Model">
24   </many-to-many>
25   </bag>
26   </class>
27  </hibernate-mapping>
28

對應的實體類:

代碼

using System;
using System.Collections;
namespace NHibernateSample.Model
{
   #region Course
   /// <summary>
   /// Course object for NHibernate mapped table  'Course'.
   /// </summary>
   public class Course
   {
     #region Member Variables
     protected int _id;
     protected string _courseName;
     protected string _teacher;
     protected DateTime _time;
     protected string _address;
     //protected IList _courseSelectCourses;
     protected IList _Students;
     #endregion
     #region Constructors
     public Course() { }
     public Course( string courseName, string teacher,  DateTime time, string address )
     {
       this._courseName = courseName;
       this._teacher = teacher;
       this._time = time;
       this._address = address;
     }
     #endregion
     #region Public Properties
     public virtual int Id
     {
       get {return _id;}
       set {_id = value;}
     }
     public virtual string CourseName
     {
       get { return _courseName; }
       set
       {
         if ( value != null && value.Length  > 50)
           throw new ArgumentOutOfRangeException ("Invalid value for CourseName", value, value.ToString());
         _courseName = value;
       }
     }
     public virtual string Teacher
     {
       get { return _teacher; }
       set
       {
         if ( value != null && value.Length  > 50)
           throw new ArgumentOutOfRangeException ("Invalid value for Teacher", value, value.ToString());
         _teacher = value;
       }
     }
     public virtual DateTime Time
     {
       get { return _time; }
       set { _time = value; }
     }
     public virtual string Address
     {
       get { return _address; }
       set
       {
         if ( value != null && value.Length  > 50)
           throw new ArgumentOutOfRangeException ("Invalid value for Address", value, value.ToString());
         _address = value;
       }
     }
     public virtual IList Students
     {
       get 
       {
         if (_Students == null)
         {
           _Students = new ArrayList();
         }
         return _Students;
       }
       set { _Students = value; }
     }
     #endregion
   }
   #endregion
}

對於實體類,就不用說了。主要說說映射文件中的<bag>節點的配置。

bag:對象集合。集合中的元素可以重復。相當於.Net中的IList或者 IList<T>。當然對應的name是相應實體類的屬性了。

我個人最為關鍵的的是KEY、與many-to-mnay兩個階段的配置與理解。首先對 於兩個實體類,我應該建立他們各自的映射文件,這是最基本的。我就以Course 表來說。它與Students表多對多的關系是通過SelectCourse表建立的。要給 Course實體類建立與Students的映射關系,唯一的途徑就是通過SelectCourse表 上的外鍵FK_SelectCourse_Course。而外鍵FK_SelectCourse_Course是引用的 Course表的主鍵。

所以對key節點:他對應的column【對應表的列明,這裡就不再具體多說】當 然是CourseID。

對於many-to-many節點,我是這樣理解的。既然是多對多。第一個many指的當 然是它自己,即Order,另外一個顯然是針對Students。那麼Students與Course 建立對應關系的唯一途徑也只有通過引用在它的主鍵上建立的外鍵 FK_SelectCourse_Students。後面對應的是實體類Students對應的程序集以及指 明Course多對多的實體類Student。

映射文件小結:

key節點:是對於映射文件對應的實體類所說的。
many-to-many:是對多對多中另外“多”的一方說的

映射文件的介紹與說明就到這。下面說說它們之間該如何做操作。我僅僅以 添加為例進行說明。

添加的需求說明:我希望為一個學生添加他所選的課程,並將此學生添加到 一個新的班級中【課程也要求新添加到課程表】。還是直接上代碼較為直接:

 1 //申明對象
  2        Class cls = new Class();
  3       Student stu = new Student();
  4       SelectCourse sCourse = new SelectCourse();
  5       Course c = new Course();
  6
  7       cls.ClassCode = "03510236";
  8       cls.ClassStudentses.Add(stu);
  9       cls.StudentsAmount = 36;
10
11       stu.Class = cls;
12       stu.Name = "teau";
13       stu.Phone = "0897658";
14
15       sCourse.Course = c;
16       sCourse.Student = stu;
17
18       c.Address = "Beijing";
19       c.CourseName = "C++";
20       c.CourseSelectCourses.Add(sCourse);
21       c.Teacher = "Tao";
22       c.Time = DateTime.Now;
23
24
25       ClassesBLL cBLl = new ClassesBLL();
26       CourseBLL courseBLL = new CourseBLL();
27       try
28       {
29         if (cBLl != null && cls !=null)
30         {
31           cBLl.AddStudent(cls);
32           courseBLL.AddCourse(c);
33         }
34       }
35       catch(Exception ex)
36       {
37         throw ex;
38       }
39

上述添加需求的代碼時候就這些,其中關於業務實體類通過ISession會話操 作數據庫的代碼就不再給出。相信只要了解Nhibernate基礎只是的都能知道是如 何操作的。

說了這麼多,多對多的映射到這就說完了。我個人覺得多對多的問題也就是 通過中間結構構成的多對多。假如在本例中,我們要完成上述例子中的添加需求 ,能不能不通過多對多的關系操作呢?我覺得一點問題也沒有。因為對Studet表 與SelectCourse表,它們對應的實體關系之間就是一對多的關系。同樣對 SelectCourse實體與Course實體,它們之間也是一對多的關系。如果我們把 Student與Course的關系分開來看,其實就是兩個一對多的過程。通過一對多的 關系也可以解決。

總結:多對多的關系是Nhibernate映射配置中比較難也比較繞的一部分【我 個人覺得】。但是只要理解其中key和many-to-many各自配置的作用,以及為何 是通過這樣配置的,問題也就迎刃而解了。

就寫到這了,希望對各位有所幫組,若有理解或者表述有誤的也希望大俠們 踴躍拍磚!

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