NHibernate从入门到精通系列(7)——多对一关联映射
?
內(nèi)容摘要
多對一關(guān)聯(lián)映射概括
多對一關(guān)聯(lián)映射插入和查詢
多對一關(guān)聯(lián)映配置介紹
?
一、多對一關(guān)聯(lián)映射概括
關(guān)聯(lián)關(guān)系是實體類與實體類之間的結(jié)構(gòu)關(guān)系,分別為“多對一”、“一對一”、“多對多”。然而“多對一”是怎樣描述的呢?讓我們參考圖1.1所示:
圖1.1
?
學(xué)生表“T_Student”有兩條記錄,它們分別對應(yīng)了班級表“T_Class”的主鍵值為“1”的同一條記錄。所以這就是“多對一”的使用情景。
讓我們看一下“多對一”持久化類的結(jié)構(gòu):
????public?class?Class
????{
????????public?virtual?int??ID?{?get;?set;?}
????????public?virtual?string?Name?{?get;?set;?}
????}
????public?class?Student
????{
????????public?virtual?int??ID?{?get;?set;?}
????????public?virtual?string?Name?{?get;?set;?}
????????public?virtual?Class?Class?{?get;?set;?}
????}
?
在“Student”類中有類型為“Class”的屬性,這就意味著在“Student”有一個與之對應(yīng)的“Class”類。
再讓我們看一下映射文件:
?
<class?name="Class"?table="T_Class"?lazy="true"?>????<id?name="ID"?type="int"?column="ClassID">
??????<generator?class="native"/>
????</id>
??
????<property?name="Name"?type="string">
??????<column?name="Name"?length="50"/>
????</property>
??</class>
??<class?name="Student"?table="T_Student"?lazy="true"?>
????<id?name="ID"?type="int"?column="StudentID">
??????<generator?class="native"/>
????</id>
??
????<property?name="Name"?type="string">
??????<column?name="Name"?length="50"/>
????</property>
????<many-to-one?name="Class"?column="ClassID"/>
????
??</class>
?
我在“Student”類的映射文件中發(fā)現(xiàn)了“many-to-one”節(jié)點,<many-to-one>標(biāo)簽是描述“多對一”的關(guān)聯(lián)映射。
該標(biāo)簽的name屬性是“多對一”的類名,column是外鍵字段名。
我們配置好映射文件后運行程序,生成的表結(jié)構(gòu)如圖1.2所示:
圖1.2
?
發(fā)現(xiàn)NHibernate幫我們生成了一個外鍵。
?
二、多對一關(guān)聯(lián)映射插入和查詢
2.1 多對一關(guān)聯(lián)映射插入
我們編寫一個測試類,測試一下“多對一”關(guān)聯(lián)映射的插入。
? 代碼如下:
?
?[TestFixture]????public?class?NHibernateInit
????{
????????private?ISessionFactory?sessionFactory;
????????[SetUp]
????????public?void?InitTest()
????????{
????????????var?cfg?=?new?NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");
????????????sessionFactory?=?cfg.BuildSessionFactory();
????????}
????????[Test]
????????public?void?Save()
????????{
????????????using?(ISession?session?=?this.sessionFactory.OpenSession())
????????????{
????????????????var?cls?=?new?Class?{?Name?=?"1班"?};
????????????????var?liu?=?new?Student?{?Name?=?"劉冬",?Class?=?cls?};
????????????????var?zhang?=?new?Student?{?Name?=?"張三",?Class?=?cls?};
????????????????ITransaction?tran?=?session.BeginTransaction();
????????????????try
????????????????{
????????????????????session.Save(liu);
????????????????????session.Save(zhang);
????????????????????tran.Commit();
????????????????}
????????????????catch(Exception?ex)?
????????????????{
????????????????????tran.Rollback();
????????????????????throw?ex;
????????????????}
????????????}
????????}
????}
?
使用NUnit運行測試類。如圖2.1.1所示,發(fā)現(xiàn)拋出“object references an unsaved transient instance - save the transient instance before flushing. Type: Domain.Class, Entity: Domain.Class”這樣的異常。
圖2.1.1
?
這個異常是怎么回事呢?持久化“Student”類的實例后,“Student”類的實例變?yōu)?strong>“持久態(tài)(Persistent)”,而“Class”類的實例還是臨時態(tài)(Transient),當(dāng)持久化一個持久態(tài)的實例時,若該實例引用了一個臨時態(tài)的實例,就會拋出這樣的異常。
我們修改一下代碼:
[Test]
????????public?void?Save()
????????{
????????????using?(ISession?session?=?this.sessionFactory.OpenSession())
????????????{
????????????????var?cls?=?new?Class?{?Name?=?"1班"?};
????????????????var?liu?=?new?Student?{?Name?=?"劉冬",?Class?=?cls?};
????????????????var?zhang?=?new?Student?{?Name?=?"張三",?Class?=?cls?};
????????????????ITransaction?tran?=?session.BeginTransaction();
????????????????try
????????????????{
????????????????????//持久化“Class”類
????????????????????session.Save(cls);
????????????????????session.Save(liu);
????????????????????session.Save(zhang);
????????????????????tran.Commit();
????????????????}
????????????????catch(Exception?ex)?
????????????????{
????????????????????tran.Rollback();
????????????????????throw?ex;
????????????????}
????????????}
????????}
?
? 然后運行修改過的程序。如圖2.1.2所示,運行成功。
圖2.1.2
同理,我們也可以修改<many-to-one>標(biāo)簽中的cascade屬性為“all”,這樣就能實現(xiàn)同樣的效果。設(shè)置cascade屬性后,當(dāng)持久態(tài)的實例引用臨時態(tài)的實例時,NHibernate就會幫我們把這個臨時態(tài)的實例自動持久化到數(shù)據(jù)庫中。
?
2.2 多對一關(guān)聯(lián)映射查詢
我們編寫一個查詢方法,當(dāng)獲取到“Student”時,可以通過其“Class”屬性讀取“Class”的信息。
?
??????? [Test]????????public?void?Select()
????????{
????????????using?(ISession?session?=?this.sessionFactory.OpenSession())
????????????{
????????????????var?student?=?session.CreateQuery("?from?Student").List<Student>().First();
????????????????Console.WriteLine("學(xué)生名為:{0}",?student.Name);
????????????????Console.WriteLine("班級名為:{0}",?student.Class.Name);
????????????}
????????}
?
運行效果如圖2.2.1所示,我們并沒有再去調(diào)用查詢方法,就能獲取到關(guān)聯(lián)的信息。
圖2.2.1
?
三、多對一關(guān)聯(lián)映配置介紹
<many-to-onename="PropertyName" 屬性名column="column_name" 數(shù)據(jù)庫字段名class="ClassName" 關(guān)聯(lián)的類的名字cascade="all|none|save-update|delete" 級聯(lián)關(guān)系fetch="join|select" 抓取update="true|false" insert="true|false" property-ref="PropertyNameFromAssociatedClass" 指定關(guān)聯(lián)類的一個屬性,這個屬性將會和本外鍵相對應(yīng)access="field|property|nosetter|ClassName" unique="true|false" 是否生成一個唯一約束optimistic-lock="true|false" not-found="ignore|exception" 指定外鍵引用的數(shù)據(jù)不存在時如何處理/>
?
代碼下載
出處:http://www.cnblogs.com/GoodHelper/archive/2011/02/24/nhibernate07.html
歡迎轉(zhuǎn)載,但需保留版權(quán)。
轉(zhuǎn)載于:https://www.cnblogs.com/GoodHelper/archive/2011/02/24/nhibernate07.html
總結(jié)
以上是生活随笔為你收集整理的NHibernate从入门到精通系列(7)——多对一关联映射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux access函数判断文件存取
- 下一篇: 开家串串店需要多少成本