前言
現(xiàn)代化大型項目通常使用獨立的數(shù)據(jù)庫來存儲數(shù)據(jù),其中以采用關(guān)系型數(shù)據(jù)庫居多。用于開發(fā)項目的高級語言(c#、java等)是面向?qū)ο蟮模P(guān)系型數(shù)據(jù)庫是基于關(guān)系的,兩者之間的溝通需要一種轉(zhuǎn)換,也就是對象/關(guān)系數(shù)據(jù)庫映射(object/relational mapping,簡稱orm)。
c#可用以解決對象/關(guān)系數(shù)據(jù)庫映射的工具有多種,常見的有ef (entity framework)、nhibernate、ibatis等,各自的優(yōu)缺點及適用場景在此不做討論,本文只對如何使用nhibernate做個總結(jié)。
nhibernate是一個面向.net環(huán)境的對象/關(guān)系數(shù)據(jù)庫映射工具。
1. 創(chuàng)建項目文件
在visual studio開發(fā)工具里創(chuàng)建需要的項目結(jié)構(gòu)。
2. 添加對nhibernate的引用
當下載并解壓nhibernate安裝包后,電腦上就會創(chuàng)建一些目錄,包括“required_bins”,要把 required_bins目錄下的dll引用到項目里來,它們是nhibernate使用的核心組件。
nhibernate.dll(基礎(chǔ)類庫,與數(shù)據(jù)庫直接打交道,位于數(shù)據(jù)訪問層)
iesi.collections(基礎(chǔ)類庫輔助類庫,位于數(shù)據(jù)訪問層)
antlr3.runtime(基礎(chǔ)類庫輔助類庫,位于數(shù)據(jù)訪問層)
nhibernate.bytecode.spring.dll(proxy factory類庫,用于打開/關(guān)閉nhibernate session,位于數(shù)據(jù)訪問層工具類庫)
圖1 添加對nhibernate的引用
3. 配置nhibernate
文件:hibernate.cfg.xml,位于站點根目錄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<? xml version = "1.0" encoding = "utf-8" ?> < hibernate-configuration xmlns = "urn:nhibernate-configuration-2.2" > < session-factory > < property name = "connection.driver_class" >nhibernate.driver.sqlclientdriver</ property > < property name = "connection.connection_string" > data source=120.120.200.200;initial catalog=mamall;persist security info=true;user id=mamall;password=mima123;connection reset=false;connection lifetime=50;min pool size=1;max pool size=500 </ property > < property name = "adonet.batch_size" >10</ property > < property name = "show_sql" >true</ property > < property name = "dialect" >nhibernate.dialect.mssql2005dialect</ property > < property name = "command_timeout" >10</ property > < property name = "query.substitutions" >true 1, false 0, yes 'y', no 'n'</ property > < property name = "proxyfactory.factory_class" > nhibernate.bytecode.spring.proxyfactoryfactory,nhibernate.bytecode.spring</ property > < property name = "connection.release_mode" >on_close</ property > < mapping assembly = "fuli.entity" /> </ session-factory > </ hibernate-configuration > |
4. 編寫nhibernatehelper輔助類
文件:nhibernatehelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using system; using fuli.tool.log; using nhibernate; using nhibernate.cfg; namespace fuli.dal.common { public class nhibernatehelper { private static isessionfactory _sessionfactory; private static isessionfactory sessionfactory { get { if (_sessionfactory == null ) { var configuration = new configuration(); configuration.configure(); _sessionfactory = configuration.buildsessionfactory(); } return _sessionfactory; } } public static isession opensession() { try { return sessionfactory.opensession(); } catch (exception ex) { loghelper.getinstance().writemessage( "打開數(shù)據(jù)庫失敗,錯誤:" + ex.tostring()); return null ; } } } } |
5. 創(chuàng)建數(shù)據(jù)模型
nhibernate允許直接使用plain old clr objects (pocos),而不用通過存儲過程來直接和數(shù)據(jù)庫交互。使用pocos的一個優(yōu)勢在于不用綁定特定的持久化層。相比較而言,有些orm解決方案需要特殊屬性,或者是基于模型對象,這些對象又是從特定的基類中繼承而來的。
在nhibernate中不用特殊的修飾就可以讓對象和持久化層交互。要注意的是所有需要持久化的屬性必須是虛擬的,并且要開啟延遲加載,所有數(shù)據(jù)模型類中的公共方法必須是虛擬的,哪怕它們并沒有包含到映射文件中。
通常來講,最好把所有的屬性都設(shè)置為虛擬的。
可以借助mygeneration自動代碼工具從數(shù)據(jù)表生成數(shù)據(jù)模型和對應(yīng)的映射文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
using system; using system.collections.generic; namespace fuli.entity.domain { /// <summary> /// 共享編碼表(字典表) /// </summary> [serializable] public class sharedcode { #region 構(gòu)造方法 public sharedcode() { m_id = 0; m_category = string .empty; m_text = string .empty; m_value = string .empty; m_isdefault = false ; m_description = string .empty; m_parentid = 0; m_sortorder = 0; } #endregion 構(gòu)造方法 #region 私有變量 private long m_id; private string m_category; private string m_text; private string m_value; private bool m_isdefault; private string m_description; private long m_parentid; private short m_sortorder; #endregion 私有變量 #region 公有屬性 ///<summary> /// 主鍵id ///</summary> public virtual long id { get { return m_id; } set { m_id = value; } } ///<summary> /// 分類 ///</summary> public virtual string category { get { return m_category; } set { m_category = value; } } ///<summary> /// 文本 ///</summary> public virtual string text { get { return m_text; } set { m_text = value; } } ///<summary> /// 編碼值 ///</summary> public virtual string value { get { return m_value; } set { m_value = value; } } ///<summary> /// 是否是同類里默認 ///</summary> public virtual bool isdefault { get { return m_isdefault; } set { m_isdefault = value; } } ///<summary> /// 描述 ///</summary> public virtual string description { get { return m_description; } set { m_description = value; } } ///<summary> /// 父級id(如果有) ///</summary> public virtual long parentid { get { return m_parentid; } set { m_parentid = value; } } ///<summary> /// 排列次序 ///</summary> public virtual short sortorder { get { return m_sortorder; } set { m_sortorder = value; } } #endregion 公有屬性 #region 擴展屬性 #endregion 擴展屬性 #region rewrite equals and hashcode /// <summary> /// /// </summary> public override bool equals( object obj) { if ( this == obj) return true ; if ((obj == null ) || (obj.gettype() != gettype())) return false ; sharedcode castobj = (sharedcode)obj; return (castobj != null ) && (m_id == castobj.id); } /// <summary> /// 用唯一值實現(xiàn)gethashcode /// </summary> public override int gethashcode() { int hash = 57; hash = 27 * hash * m_id.gethashcode(); return hash; } #endregion rewrite equals and hashcode } } |
6. 創(chuàng)建nhibernate映射文件
nhibernate使用xml映射文件來映射poco到數(shù)據(jù)庫對象。雖然在很多案例中這可能是一對一關(guān)系,但這并不是必定的。
文件:sharedcode.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<? xml version = "1.0" encoding = "utf-8" ?> < hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" > < class name = "fuli.entity.domain.sharedcode, fuli.entity" table = "sharedcode" > < id name = "id" column = "id" type = "int64" unsaved-value = "0" > < generator class = "native" /> </ id > < property name = "category" type = "string" column = "category" /> < property name = "text" type = "string" column = "text" /> < property name = "value" type = "string" column = "value" /> < property name = "isdefault" type = "boolean" column = "isdefault" /> < property name = "description" type = "string" column = "description" /> < property name = "parentid" type = "int64" column = "parentid" /> < property name = "sortorder" type = "int16" column = "sortorder" /> </ class > </ hibernate-mapping > |
在hibernate-maping標簽中,同時引用類集(pocos)所屬的程序集命名空間。
- class元素表示到單個poco的映射。name表示上面的程序集和命名空間中的類名,table屬性告訴nhibernate數(shù)據(jù)庫中的哪個表或者視圖將被映射。
- id元素告訴nhibernate哪個數(shù)據(jù)庫的字段和對應(yīng)的對象作為一個唯一鍵來使用。在本例中,我們使用id這個字段。
- generator元素告訴nhibernate怎樣給新實體來創(chuàng)建唯一id。
- property標簽是見得最多的標簽。它簡單地映射一個到數(shù)據(jù)表或者視圖中對應(yīng)字段的映射。
一旦xml文件創(chuàng)建好了,需要更改xml的生成方式確保它被設(shè)置為嵌入式資源,否則nhibernate不會讀取這個xml文件,那么映射就不會生效了。
圖2 映射文件必須是嵌入的資源
7. 使用 nhibernate連接數(shù)據(jù)庫
文件:commonrepository
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
|
namespace fuli.dal.sqlserverimpl { public class commonrepository : icommonrepository { #region 新增 /// <summary> /// 新增實體表 /// </summary> /// <param name="obj"></param> /// <returns></returns> public long addnewentity<t>( object obj, string tablename) where t : new () { long id = 0; try { using (isession session = nhibernatehelper.opensession()) { id = long .parse(session.save((t)obj).tostring()); session.flush(); } } catch (exception ex) { loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring()); } return id; } /// <summary> /// 新增實體表 /// </summary> /// <param name="entity"></param> /// <returns></returns> public treturn addnewentity<tentity, treturn>( object entity, string tablename) where tentity : new () { treturn returnvalue = default (treturn); try { using (isession session = nhibernatehelper.opensession()) { object returnobject = session.save(entity); if (returnobject != null ) { returnvalue = (treturn)convert.changetype(returnobject, typeof (treturn)); } session.flush(); } } catch (exception ex) { loghelper.getinstance().writemessage(tablename + operationtype.comma + ex.tostring()); } return returnvalue; } #endregion 新增 } } |
對于不同的實體,可以一對一地寫一個<entity>repository,專注負責相對應(yīng)的實體操作。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。
原文鏈接:http://www.cnblogs.com/ywqu/p/8664360.html