天天看點

NHibernate多對多關聯映射的實作

上次用EF示範了資料庫多對多關系的操作,這次我們還是引用上次的案例,來示範如何在C#當中使用NHibernate。

1、下載下傳NHibernate

官網首頁就有下載下傳連結,直接下載下傳就可以了。

下載下傳好之後會得到一個zip包。

NHibernate多對多關聯映射的實作

我們就地解壓可以看到如下目錄和檔案:

NHibernate多對多關聯映射的實作

我們重點關注以下目錄的内容:

Configuration_Templates目錄:預設提供的一些配置模闆。有支援Oracle、Sql Server、MySQL等等。

Required_Bins目錄:這裡面存放了我們開發時常用的dll檔案。其中的兩個xsd檔案是能夠提供智能提示的檔案,我們需要将它們倆複制到你本地的VS的Schemas目錄下,比如我的目錄為:D:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas 。

NHibernate多對多關聯映射的實作

複制好之後,重新開機VS,在我們寫Hibernate配置檔案時就有了智能提示了。

NHibernate多對多關聯映射的實作

準備工作做好之後,我們就可以正式示範。

2、建立一個類庫項目Model

我們定義好兩個類,分别為Student和Subject,為了便于管理,我們将它們放到Entity檔案夾裡,但命名空間仍為Model。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code>namespace</code> <code>Model</code>

<code>{</code>

<code>    </code><code>public</code> <code>enum</code> <code>Gender { Female, Male }</code>

<code>                                         </code> 

<code>    </code><code>public</code> <code>class</code> <code>Student</code>

<code>    </code><code>{</code>

<code>        </code><code>public</code> <code>virtual</code> <code>int</code><code>? StudentId { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>virtual</code> <code>string</code> <code>StudentName { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>virtual</code> <code>Gender Gender { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>virtual</code> <code>DateTime? BirthDay { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>virtual</code> <code>IList&lt;Subject&gt; Subjects { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>    </code><code>}</code>

<code>}</code>

<code>    </code><code>public</code> <code>class</code> <code>Subject</code>

<code>        </code><code>public</code> <code>virtual</code> <code>int</code><code>? SubjectId { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>virtual</code> <code>string</code> <code>SubjectName { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>                                       </code> 

<code>        </code><code>public</code> <code>virtual</code> <code>IList&lt;Student&gt; Students { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

這是一個典型的多對多的應用場景。一個學生可以選修多個課程,一個課程可以被多個學生選修。

接下來我們再建立相應的Hibernate配置檔案(就是普通的xml檔案,取名為Student.hbm.xml和Subject.hbm.xml)。

Student.hbm.xml:

15

16

17

18

19

20

21

<code>&lt;?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"utf-8"</code> <code>?&gt;</code>

<code>&lt;</code><code>hibernate-mapping</code> <code>xmlns</code><code>=</code><code>"urn:nhibernate-mapping-2.2"</code> <code>assembly</code><code>=</code><code>"Model"</code> <code>namespace</code><code>=</code><code>"Model"</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>class</code> <code>name</code><code>=</code><code>"Student"</code> <code>table</code><code>=</code><code>"T_Student"</code> <code>lazy</code><code>=</code><code>"true"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>id</code> <code>name</code><code>=</code><code>"StudentId"</code>  <code>type</code><code>=</code><code>"int"</code> <code>column</code><code>=</code><code>"StudentId"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>generator</code> <code>class</code><code>=</code><code>"native"</code><code>/&gt;</code>

<code>    </code><code>&lt;/</code><code>id</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"StudentName"</code> <code>type</code><code>=</code><code>"string"</code> <code>column</code><code>=</code><code>"StudentName"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>column</code> <code>name</code><code>=</code><code>"StudentName"</code> <code>length</code><code>=</code><code>"50"</code><code>/&gt;</code>

<code>    </code><code>&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"Gender"</code> <code>type</code><code>=</code><code>"Gender"</code> <code>column</code><code>=</code><code>"Gender"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>column</code> <code>name</code><code>=</code><code>"Gender"</code> <code>length</code><code>=</code><code>"4"</code><code>/&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"BirthDay"</code> <code>type</code><code>=</code><code>"datetime"</code> <code>column</code><code>=</code><code>"BirthDay"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>column</code> <code>name</code><code>=</code><code>"BirthDay"</code> <code>length</code><code>=</code><code>"20"</code><code>/&gt;</code>

<code>    </code><code>&lt;</code><code>bag</code> <code>name</code><code>=</code><code>"Subjects"</code> <code>table</code><code>=</code><code>"T_Student_Subject"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>key</code> <code>column</code><code>=</code><code>"StudentId"</code><code>/&gt;</code>

<code>      </code><code>&lt;</code><code>many-to-many</code> <code>class</code><code>=</code><code>"Subject"</code> <code>column</code><code>=</code><code>"SubjectId"</code><code>/&gt;</code>

<code>    </code><code>&lt;/</code><code>bag</code><code>&gt;</code>

<code>  </code><code>&lt;/</code><code>class</code><code>&gt;</code>

<code>&lt;/</code><code>hibernate-mapping</code><code>&gt;</code>

Subject.hbm.xml:

<code>  </code><code>&lt;</code><code>class</code> <code>name</code><code>=</code><code>"Subject"</code> <code>table</code><code>=</code><code>"T_Subject"</code> <code>lazy</code><code>=</code><code>"true"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>id</code> <code>name</code><code>=</code><code>"SubjectId"</code> <code>type</code><code>=</code><code>"int"</code> <code>column</code><code>=</code><code>"SubjectId"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"SubjectName"</code> <code>type</code><code>=</code><code>"string"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>column</code> <code>name</code><code>=</code><code>"SubjectName"</code> <code>length</code><code>=</code><code>"50"</code><code>/&gt;</code>

<code>    </code><code>&lt;</code><code>bag</code> <code>name</code><code>=</code><code>"Students"</code> <code>table</code><code>=</code><code>"T_Student_Subject"</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>key</code> <code>column</code><code>=</code><code>"SubjectId"</code><code>/&gt;</code>

<code>      </code><code>&lt;</code><code>many-to-many</code> <code>class</code><code>=</code><code>"Student"</code> <code>column</code><code>=</code><code>"StudentId"</code><code>/&gt;</code>

便于管理我們同樣的放到Config目錄下(自己建立的檔案夾)。

同時修改兩個xml檔案的生成操作由内容變為嵌入的資源(在vs中右鍵xml檔案選擇屬性)

NHibernate多對多關聯映射的實作

3、建立一個控制台應用程式

表和實體對應的内容已經定義好,下面關鍵的就是要寫代碼來測試NHibernate了,本着盡量降低學習難度的原則,我這裡就用控制台應用程式來驗證(你也可以建立一個類庫項目,然後用VS的單元測試或者第三方測試工具NUnit進行驗證)。

首先将下載下傳的開發包裡面的Configuration_Templates檔案夾下的MSSQL.cfg.xml複制到控制台應用程式中(為友善管理,我建立了一個Config檔案夾,并把這個xml檔案放到這裡面,重命名為hibernate.cfg.xml)。

修改這個xml檔案内容為:

<code>&lt;?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"utf-8"</code><code>?&gt;</code>

<code>&lt;!--</code>

<code>This template was written to work with NHibernate.Test.</code>

<code>Copy the template to your NHibernate.Test project folder and rename it in hibernate.cfg.xml and change it</code>

<code>for your own use before compile tests in VisualStudio.</code>

<code>--&gt;</code>

<code>&lt;!-- This is the System.Data.dll provider for SQL Server --&gt;</code>

<code>&lt;</code><code>hibernate-configuration</code>  <code>xmlns</code><code>=</code><code>"urn:nhibernate-configuration-2.2"</code> <code>&gt;</code>

<code>  </code><code>&lt;</code><code>session-factory</code> <code>name</code><code>=</code><code>"NHibernate.Test"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"connection.driver_class"</code><code>&gt;NHibernate.Driver.SqlClientDriver&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"connection.connection_string"</code><code>&gt;</code>

<code>      </code><code>Server=.;database=nhibernateTest;uid=sa;pwd=123456;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"adonet.batch_size"</code><code>&gt;10&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"show_sql"</code><code>&gt;true&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"hbm2ddl.auto"</code><code>&gt;update&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"dialect"</code><code>&gt;NHibernate.Dialect.MsSql2008Dialect&lt;/</code><code>property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>mapping</code> <code>assembly</code><code>=</code><code>"Model"</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>session-factory</code><code>&gt;</code>

<code>&lt;/</code><code>hibernate-configuration</code><code>&gt;</code>

注意這裡面的一些節點的配置。比如mapping assembly裡面的Model,就是指的是程式集的名稱。同時将此檔案的複制到輸出目錄方式修改為始終複制。

NHibernate多對多關聯映射的實作

接下來,給控制台項目添加兩個dll的引用,分别為Iesi.Collections.dll和NHibernate.dll,也是在Required_Bins檔案夾裡面。

添加好引用,我們建立一個新的類NHibernateTest來寫關鍵性代碼。

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

<code>namespace</code> <code>NHibernateDemo</code>

<code>    </code><code>public</code> <code>class</code> <code>NHibernateTest</code>

<code>        </code><code>private</code> <code>ISessionFactory _sessionFactory;</code>

<code>        </code><code>public</code> <code>ISessionFactory SessionFactory</code>

<code>        </code><code>{</code>

<code>            </code><code>get</code>

<code>            </code><code>{</code>

<code>                </code><code>if</code> <code>(_sessionFactory == </code><code>null</code><code>)</code>

<code>                </code><code>{</code>

<code>                    </code><code>var</code> <code>cfg = </code><code>new</code> <code>NHibernate.Cfg.Configuration().Configure(</code><code>"Config/hibernate.cfg.xml"</code><code>);</code>

<code>                    </code><code>_sessionFactory = cfg.BuildSessionFactory();</code>

<code>                </code><code>}</code>

<code>                </code><code>return</code> <code>_sessionFactory;</code>

<code>            </code><code>}</code>

<code>        </code><code>}</code>

<code>                  </code> 

<code>        </code><code>public</code> <code>void</code> <code>TestInit()</code>

<code>            </code><code>using</code> <code>(ISession session = SessionFactory.OpenSession())</code>

<code>                </code><code>IList&lt;Subject&gt; subjects = </code><code>new</code> <code>List&lt;Subject&gt;()</code>

<code>                     </code><code>new</code> <code>Subject { SubjectName = </code><code>"數學"</code> <code>},</code>

<code>                     </code><code>new</code> <code>Subject { SubjectName = </code><code>"英語"</code> <code>},</code>

<code>                     </code><code>new</code> <code>Subject { SubjectName = </code><code>"計算機"</code> <code>},</code>

<code>                </code><code>};</code>

<code>                </code><code>IList&lt;Student&gt; students = </code><code>new</code> <code>List&lt;Student&gt;()</code>

<code>                    </code><code>new</code> <code>Student</code>

<code>                    </code><code>{</code>

<code>                        </code><code>StudentName = </code><code>"guwei4037"</code><code>,</code>

<code>                        </code><code>Gender = Gender.Male,</code>

<code>                        </code><code>BirthDay = </code><code>new</code> <code>DateTime(1984, 11, 25),</code>

<code>                        </code><code>Subjects = subjects.Where(x =&gt; x.SubjectName == </code><code>"數學"</code> <code>|| x.SubjectName == </code><code>"計算機"</code><code>).ToArray(),</code>

<code>                    </code><code>},</code>

<code>                        </code><code>StudentName = </code><code>"gary.gu"</code><code>,</code>

<code>                        </code><code>Gender = Gender.Female,</code>

<code>                        </code><code>BirthDay = </code><code>new</code> <code>DateTime(1987, 9, 15),</code>

<code>                        </code><code>Subjects = subjects.Where(x =&gt; x.SubjectName == </code><code>"數學"</code> <code>|| x.SubjectName == </code><code>"英語"</code><code>).ToArray(),</code>

<code>                </code><code>ITransaction tran = session.BeginTransaction();</code>

<code>                </code><code>try</code>

<code>                    </code><code>foreach</code> <code>(</code><code>var</code> <code>subject </code><code>in</code> <code>subjects)</code>

<code>                        </code><code>session.Save(subject);</code>

<code>                    </code><code>}</code>

<code>                    </code><code>foreach</code> <code>(</code><code>var</code> <code>student </code><code>in</code> <code>students)</code>

<code>                        </code><code>session.Save(student);</code>

<code>                    </code><code>tran.Commit();</code>

<code>                </code><code>catch</code> <code>(Exception ex)</code>

<code>                    </code><code>tran.Rollback();</code>

<code>                    </code><code>throw</code> <code>ex;</code>

這是一個帶事務的多表插入的操作。

最後在Main方法中,寫入簡單的調用方法。

<code>public</code> <code>class</code> <code>program</code>

<code>   </code><code>{</code>

<code>       </code><code>public</code> <code>static</code> <code>void</code> <code>Main(</code><code>string</code><code>[] args)</code>

<code>       </code><code>{</code>

<code>           </code><code>NHibernateTest test = </code><code>new</code> <code>NHibernateTest();</code>

<code>           </code><code>test.TestInit();</code>

<code>       </code><code>}</code>

<code>   </code><code>}</code>

在運作這個程式之前,還要做一件事,就是要在你的Sql Server中建立一個空的資料庫nhibernateTest,否則會提示登入失敗。

好了,這時我們已經準備好了一切,讓我們運作一下這個控制台應用程式吧。

由于我們在hibernate.cfg.xml檔案中定義了輸入sql,是以會看到視窗中的内容。

NHibernate多對多關聯映射的實作

好,沒有報錯。我們打開Sql Server看一下最終的結果。

NHibernate多對多關聯映射的實作

而且資料庫的表、主外鍵的關聯以及資料都為我們自動生成了。

本文轉自 guwei4037  51CTO部落格,原文連結:http://blog.51cto.com/csharper/1359457