快捷搜索:

NHibernate学习手记(6) - 实现one2many/many2one的映射

本文示例源代码或素材下载

根据约定,本文将经由过程Category和Item工具来描述one2many的关系,即一个Category工具对应多个Item工具。

主要内容:

1、编写POCO类

2、筹备数据库

3、编写设置设置设备摆设摆设文件

4、级连(cascading)操作示例

一、编写POCO类

从手记(6)起我盘算由编写POCO类开始描述,由于NHibernate已经让我们以工具的要领去思虑数据操作,数据表该怎么设计已经不是思维的动身点,更不是重点。

1、Category的POCO类:

1usingSystem;

2usingSystem.Collections;

3

4namespaceTestOne2Many

5{

6  ///

7  ///Category的择要阐明

8  ///

9  ///创建人:Aero

10  ///创建日期:2006-3-17

11  ///改感人:

12  ///改动日期:

13  ///改动内容:

14  ///版  本:

15  publicclassCategory

16  {

17    privateGuid_categoryId;

18

19    privatestring_name=string.Empty;

20

21    privateIList_items;

22

23    publicGuidCategoryID

24    {

25      get{returnthis._categoryId;}

26      set{this._categoryId=value;}

27    }

28

29    publicstringName

30    {

31      get{returnthis._name;}

32      set{this._name=value;}

33    }

34

35    publicIListItems

36    {

37      get{returnthis._items;}

38      set{this._items=value;}

39    }

40

41    #region构造函数

42    ///

43    ///默认无参构造函数

44    ///

45    ///创建人:Aero

46    ///创建日期:2006-3-17

47    ///改感人:

48    ///改动日期:

49    ///改动内容:

50    publicCategory()

51    {

52      this._items=newArrayList();

53    }

54

55    #endregion

56  }

57}

58

一对多的关系在.net代码里因此聚拢的形式去表示的,按照NH的online document的说法,NH支持三种类型的聚拢:System.Collections.IList、System.Collection.IDictionary、Iesi.Collections.ISet,在进行O/R mapping时,NH将自动把上述聚拢转化为NHibernate.Collection中对应的聚拢类型。

下面的测试代码无法经由过程,由于NH已经把Category.Items转化为NHibernate.Collection.Bag

1[Test]

2publicvoidTestCollectionType()

3{

4  using(ISessionsession=TestCategory.Factory.OpenSession())

5  {

6    //Weassumethatthereareonlyonecategoryobjectintherepository,

7    //seeinitializationinTestCategory.TestInitialize().

8    //note:cascadingoptionshouldsetas"all-delete-orphan"inobjects.hbm.xml

9    CategoryexpectedCategory=

10      session.CreateCriteria(typeof(Category)).List()[0]asCategory;

11

12    //thatworks?

13    Assert.AreEqual(expectedCategory.Items.GetType(),typeof(System.Collections.ArrayList));

14  }

15}

2、Item的POCO类:

1usingSystem;

2

3namespaceTestOne2Many

4{

5  ///

6  ///Item的择要阐明

7  ///

8  ///创建人:Aero

9  ///创建日期:2006-3-17

10  ///改感人:

11  ///改动日期:

12  ///改动内容:

13  ///版  本:

14  publicclassItem

15  {

16    privateGuid_itemId;

17

18    privatestring_name=string.Empty;

19

20    privateCategory_category;

21

22    publicGuidItemID

23    {

24      get{returnthis._itemId;}

25      set{this._itemId=value;}

26    }

27

28    publicstringName

29    {

30      get{returnthis._name;}

31      set{this._name=value;}

32    }

33

34    publicCategoryCategory

35    {

36      get{returnthis._category;}

37      set{this._category=value;}

38    }

39

40    #region构造函数

41    ///

42    ///默认无参构造函数

43    ///

44    ///创建人:Aero

45    ///创建日期:2006-3-17

46    ///改感人:

47    ///改动日期:

48    ///改动内容:

49    publicItem()

50    {

51      //

52      //TODO:在此处添加构造函数逻辑

53      //

54    }

55

56    #endregion

57  }

58}

59

二、筹备数据库

新建数据库nh_categories和nh_items,数据库设计如下:

或直接履行以下sql语句(本文示例代码所应用的数据库名称为NHTrial)

useNHTrial

GO

ifexists(select*fromdbo.sysobjectswhereid=object_id(N'[dbo].[nh_categories_nh_items_FK1]')andOBJECTPROPERTY(id,N'IsForeignKey')=1)

ALTERTABLE[dbo].[nh_items]DROPCONSTRAINTnh_categories_nh_items_FK1

GO

ifexists(select*fromdbo.sysobjectswhereid=object_id(N'[dbo].[nh_categories]')andOBJECTPROPERTY(id,N'IsUserTable')=1)

droptable[dbo].[nh_categories]

GO

ifexists(select*fromdbo.sysobjectswhereid=object_id(N'[dbo].[nh_items]')andOBJECTPROPERTY(id,N'IsUserTable')=1)

droptable[dbo].[nh_items]

GO

CREATETABLE[dbo].[nh_categories](

[CategoryID][uniqueidentifier]NOTNULL,

[Name][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL

)ON[PRIMARY]

GO

CREATETABLE[dbo].[nh_items](

[ItemID][uniqueidentifier]NOTNULL,

[CategoryID][uniqueidentifier]NOTNULL,

[Name][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL

)ON[PRIMARY]

GO

ALTERTABLE[dbo].[nh_categories]WITHNOCHECKADD

CONSTRAINT[nh_categories_PK]PRIMARYKEY CLUSTERED

(

[CategoryID]

) ON[PRIMARY]

GO

ALTERTABLE[dbo].[nh_items]WITHNOCHECKADD

CONSTRAINT[nh_items_PK]PRIMARYKEY CLUSTERED

(

[ItemID]

) ON[PRIMARY]

GO

ALTERTABLE[dbo].[nh_items]ADD

CONSTRAINT[nh_categories_nh_items_FK1]FOREIGNKEY

(

[CategoryID]

)REFERENCES[dbo].[nh_categories](

[CategoryID]

)

GO

三、编写设置设置设备摆设摆设文件

1、新建hibernate.cfg.xml文件,设置hibernate的运行设置设置设备摆设摆设信息。

NHibernate.Connection.DriverConnectionProvider

NHibernate.Driver.SqlClientDriver

Server=localhost;database=NHTrial;UserId=sa;Password=sa

false

NHibernate.Dialect.MsSql2000Dialect

true

2、新建文件objects.hbm.xml,设置设置设备摆设摆设Category和Item类的o/r mapping信息,并且把objectes.hbm.xml的属性设置为“嵌入资本”。

子非鱼在NHibernate进修里说实体xxx的mapping信息要写在xxx.hbm.xml文件里面,着实nhibernate没有这个限定,完全可以把n个实体的设置设置设备摆设摆设信息写在一个hbm.xml文件中。

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

19

20

21

22

23

25

26

27

28

部分设置设置设备摆设摆设节点的含义和用法在NHibernate进修手记(5) - 简单的工具映射里已经说过了,这里只看看bag、one-to-many和many-to-one。

1)bag节点:用于定义System.Collection.IList的类型的聚拢元素。

Attributes

Usage

Example

name

唆使映射的属性名称。Required

Items (指Category.Items)

lazy

唆使是否应用延迟加载。Optional

true | false

cascade

唆使级连操作类型。Optional

all2)级连操作选项阐明:

value

usage

none

默认值,不进行级连操作。

save-update

进行级连save和update操作

delete

进行级连删除操作

delete-orphan

删除无相关的父工具的子工具

all

进行级连save/update/delete操作

all-delete-orphan

all + delete-orphan

当进行save-update级连操作时,NH将根据子工具主键的unsave-value来判断该履行save照样update操作。

3)key节点:用于指定nh_items表顶用作外键(和nh_categories)的数据列名称

4)one-to-many节点:用于指定子工具的类型(全限制名称)

5)many-to-one节点:用于指定父工具属性,如Item.Category

Attributes

Usage

Example

name

唆使映射的属性名称。Required

Category (指Item.Category)

class

唆使唆使父工具的全限制名称。Required

TestOne2Many.Category, TestOne2Many

column

唆使子表的外键列名称。Required

CategoryID四、示例one2many的级连操作。

看过子非鱼兄的NHibernate进修后,发明用单元测试来进行代码示例切实着实是一种异常有效的要领,大年夜家只必要的是再增添一个NUnit.framework的引用:)。

1、级连添加:在保存新增的Category工具时,级连保存与之关联的Item工具

1///

2    ///demonstratehowtoexecuteathecascadingsave

3    ///

4    [Test]

5    publicvoidTestCascadingSave()

6    {

7      using(ISessionsession=TestCategory.Factory.OpenSession())

8      {

9        //preparetestobjects

10        CategoryexpectedCategory=newCategory();

11        expectedCategory.Name="category"+System.Environment.TickCount.ToString();

12

13        for(inti=0;i

2、级连更新(update):移除Category工具的部分Item子工具,保存变动后,被移除的Item子工具从数据库中删除。

1///

2    ///demonstratehowtoremovesub-itemsandexecuteacascadingupdate

3    ///

4    [Test]

5    publicvoidTestCascadingUpdate()

6    {

7      using(ISessionsession=TestCategory.Factory.OpenSession())

8      {

9        //Weassumethatthereareonlyonecategoryobjectintherepository,

10        //seeinitializationinTestCategory.TestInitialize().

11        //note:cascadingoptionshouldsetas"all-delete-orphan"inobjects.hbm.xml

12        CategoryexpectedCategory=

13          session.CreateCriteria(typeof(Category)).List()[0]asCategory;

14        intexpectedItemCount=expectedCategory.Items.Count;

15

16        //executeacascadingupdate

17        ITransactiontrans=session.BeginTransaction();

18

19        try

20        {

21          //removeanitemfromitem-collectionfromtherepository

22          expectedCategory.Items.RemoveAt(0);

23

24          session.Update(expectedCategory);

25          trans.Commit();

26        }

27        catch(System.Exceptione)

28        {

29          trans.Rollback();

30          throw;

31        }

32

33        //thatworks?

34        Assert.AreEqual(1,session.CreateCriteria(typeof(Category)).List().Count);

35        Assert.AreEqual(expectedItemCount-1,session.CreateCriteria(typeof(Item)).List().Count);

36      }

37    }

3、级连删除:当父Category工具被删除,与之关联的Item工具也被删除。

1///

2    ///demonstratehowtoexecuteacascadingdeletion

3    ///

4    [Test]

5    publicvoidTestCascadingDelete()

6    {

7      using(ISessionsession=TestCategory.Factory.OpenSession())

8      {

9        //Weassumethatthereareonlyonecategoryobjectintherepository,

10        //seeinitializationinTestCategory.TestInitialize().

11        //note:cascadingoptionshouldsetas"all-delete-orphan"inobjects.hbm.xml

12        CategoryexpectedCategory=

13          session.CreateCriteria(typeof(Category)).List()[0]asCategory;

14

15        //removecategoryfromtherepository

16        ITransactiontrans=session.BeginTransaction();

17

18        try

19        {

20          session.Delete(expectedCategory);

21          trans.Commit();

22        }

23        catch(System.Exceptione)

24        {

25          trans.Rollback();

26          throw;

27        }

28

29        //thatworks?

30        Assert.AreEqual(0,session.CreateCriteria(typeof(Category)).List().Count);

31        Assert.AreEqual(0,session.CreateCriteria(typeof(Item)).List().Count);

32      }

33    }

要特殊指出的是,NH不支持经由过程Category.Item=null这种要领来删除与Category工具关联的Item工具。

1[Test,ExpectedException(typeof(NHibernate.HibernateException))]

2    publicvoidTestCascadingUpdateFail()

3    {

4      using(ISessionsession=TestCategory.Factory.OpenSession())

5      {

6        //Weassumethatthereareonlyonecategoryobjectintherepository,

7        //seeinitializationinTestCategory.TestInitialize().

8        //note:cascadingoptionshouldsetas"all-delete-orphan"inobjects.hbm.xml

9        CategoryexpectedCategory=

10          session.CreateCriteria(typeof(Category)).List()[0]asCategory;

11        intexpectedItemCount=expectedCategory.Items.Count;

12

13        //executeacascadingupdate

14        ITransactiontrans=session.BeginTransaction();

15

16        try

17        {

18          //wecan'tremoveallitemsbydereferenceCategory.Itemsasnull,

19          //thiswillcauseaNHiberate.HibernateException

20          expectedCategory.Items=null;

21

22          //stillwecan'tremoveitemsinthefollowingway,

23          //thiswillcauseaNullReferenceExceptionfromNHibernate

24

25          //expectedCategory.Items[0]=null;

26

27          session.Update(expectedCategory);

28          trans.Commit();

29        }

30        catch(System.Exceptione)

31        {

32          trans.Rollback();

33          throw;

34        }

35

36        //thatworks?

37        Assert.AreEqual(1,session.CreateCriteria(typeof(Category)).List().Count);

38        Assert.AreEqual(expectedItemCount,session.CreateCriteria(typeof(Item)).List().Count);

39      }

40    }

完备示例代码可从ObjectMappings.rar下载,此中的TestOne2Many即本文所评论争论的工程。

您可能还会对下面的文章感兴趣: