文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>我的NHibernate之路(3)---表间多对多配置篇

我的NHibernate之路(3)---表间多对多配置篇

时间:2010-09-25  来源:tyb1222

  本节要点:

    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表对应的映射文件:

 

 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Model" namespace="NHibernateSample.Model">
<class name="NHibernateSample.Model.Course, Model" table="Course">
<id name="Id" type="Int32" unsaved-value="0">
<column name="ID" length="4" sql-type="int" not-null="true" unique="true" index="PK_Course"/>
<generator class="native" />
</id>
<property name="CourseName" type="String">
<column name="CourseName" length="50" sql-type="varchar" not-null="false"/>
</property>
<property name="Teacher" type="String">
<column name="Teacher" length="50" sql-type="varchar" not-null="false"/>
</property>
<property name="Time" type="DateTime">
<column name="`Time`" length="8" sql-type="datetime" not-null="false"/>
</property>
<property name="Address" type="String">
<column name="Address" length="50" sql-type="varchar" not-null="false"/>
</property>
<bag name="Students" generic="true" table="SelectCourse">
<key column="CourseID" foreign-key="FK_SelectCourse_Course"/>
<many-to-many column="StudentID" class="NHibernateSample.Model.Student, Model"></many-to-many>
</bag>
</class>
</hibernate-mapping>

  对应的实体类:

代码
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:是对多对多中另外“多”的一方说的

  映射文件的介绍与说明就到这。下面说说它们之间该如何做操作。我仅仅以添加为例进行说明。

 

  添加的需求说明:我希望为一个学生添加他所选的课程,并将此学生添加到一个新的班级中【课程也要求新添加到课程表】。还是直接上代码较为直接:

 

       //申明需新添加到数据库中的对象
            Class cls = new Class();
            Student stu = new Student();
            SelectCourse sCourse = new SelectCourse();
            Course c = new Course();

            //实例化班级对象
   cls.ClassCode = "03510236"; cls.ClassStudentses.Add(stu); cls.StudentsAmount = 36;    //实例化学生对象
stu.Class = cls;
stu.Name = "teau";
stu.Phone = "0897658";
       //实例化课程对象
   c.Address = "Beijing";
c.CourseName = "C++";
c.CourseSelectCourses.Add(sCourse);
c.Teacher = "Tao";
c.Time = DateTime.Now;
//实例化 选课对象
sCourse.Course = c; sCourse.Student = stu;
   //申明业务操作类对象
ClassesBLL cBLl = new ClassesBLL(); CourseBLL courseBLL = new CourseBLL(); try { if (cBLl != null && cls !=null) { cBLl.AddStudent(cls); courseBLL.AddCourse(c); } } catch(Exception ex) { throw ex; }

  上述添加需求的代码时候就这些,其中关于业务实体类通过ISession会话操作数据库的代码就不再给出。相信只要了解Nhibernate基础只是的都能知道是如何操作的。

  说了这么多,多对多的映射到这就说完了。我个人觉得多对多的问题也就是通过中间结构构成的多对多。假如在本例中,我们要完成上述例子中的添加需求,能不能不通过多对多的关系操作呢?我觉得一点问题也没有。因为对Studet表与SelectCourse表,它们对应的实体关系之间就是一对多的关系。同样对SelectCourse实体与Course实体,它们之间也是一对多的关系。如果我们把Student与Course的关系分开来看,其实就是两个一对多的过程。通过一对多的关系也可以解决。

  总结:多对多的关系是Nhibernate映射配置中比较难也比较绕的一部分【我个人觉得】。但是只要理解其中key和many-to-many各自配置的作用,以及为何是通过这样配置的,问题也就迎刃而解了。

  就写到这了,希望对各位有所帮组,若有理解或者表述有误的也希望大侠们踊跃拍砖!

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载