LINQ對SQL和NHibernate的比較(1)——linq和NHibernate初體驗
1簡介
開發壹個處理數據庫的系統,最繁瑣的就是用ADO.NET操作後臺數據庫,沒有編程樂趣,因為所有的數據庫連接、讀取、操作都是壹樣的,編程成了手工。
雖然我們可以設計自己的類作為數據庫訪問的持久層,但是每個類都必須有不同的SQL語句,這使得設計壹個統壹的數據庫讀寫類非常困難。
這種情況下,開發人員必須安排好表單設計、方法設計和數據庫讀寫設計的流程,增加了開發人員的負擔,也使得項目的維護和後期開發變得困難。
2下的ORM解決方案。網
2.1 LINQ
2.1.1 LINQ簡介
作為微軟開發的壹種查詢方案,LINQ提供了壹種更為傳統的方法來為。Net框架,可以適用於所有的信息源。這比向開發語言和運行時添加壹些關系數據特性或特定於XML的特性更好。這些語法特征被稱為。NET語言集成查詢(LINQ)。
如果妳覺得上面的解釋有點抽象,妳可以理解為LINQ其實提供了壹套查詢功能,可以實現任意數據源的查詢。在這裏,數據源不僅指數據庫或XML文件,還指任何集合或實體,例如我們需要在各種編程語言中使用的數組。現在我們不必遍歷數組元素來查找所需的項,LINQ可以實現這方面的查詢。
LINQ查詢數組:
圖2.1 LINQ查詢數組
以上是最簡單的數組LINQ查詢。泛型類型var為LINQ查詢中的委托類型提供了強大的支持。不管查詢集合中的條目類型是什麽(無論是int、char、string還是class),我們都可以只用壹個變量保存LINQ查詢的結果。程序結果如下:
圖2.2 LINQ查詢數組程序結果
方便嗎?LINQ的應用遠非這些。通過不同的映射方案,我們可以訪問數據庫(LINQ到SQL)和XML文件(LINQ到XML)。
2.1.2 LINQ簡介
表2.1 LINQ運算符
操作員
解釋
聚合
總計
對序列執行自定義方法。
平均的
計算壹個數字序列的平均值。
數數
返回序列中的項數(整數)
長計數
返回序列中的項數(長整型)
福建話
在壹系列數字中找出最小的數字
最大
找出數列中最大的數。
總和
總結序列中的數字。
連接
串聯
將兩個序列連接成壹個序列。
變化
鑄造
將序列中的元素轉換為指定的類型。
OfType
篩選序列中指定類型的元素。
ToArray
從序列中返回壹個數組。
ToDictionary
從序列中返回字典
ToList
從序列中返回壹個列表。
ToLookup
從序列中返回查詢。
to序列
返回壹個IEnumerable序列。
元素
DefaultIfEmpty
為空序列創建默認元素
元素At
返回序列中指定索引處的元素。
元素默認
返回序列中指定索引處的元素,如果索引超出範圍,則返回默認值。
第壹
返回序列中的第壹個元素。
第壹默認
返回序列中的第壹個元素,如果沒有找到元素,則返回默認值。
最後的
返回序列中的最後壹個元素。
lastor默認
返回序列中的最後壹個元素,如果沒有找到元素,則返回默認值。
單壹的
返回序列中的單個元素。
單壹或默認
返回序列中的單個元素,如果沒有找到元素,則返回默認值。
(to)與…相等
順序相等
比較兩個序列,看它們是否相等。
產生
空的
生成空序列
範圍
生成指定範圍的序列
重復
通過將壹個項目重復指定的次數來生成序列。
組
分組依據
按指定的分組方法對序列中的項目進行分組。
關系
GroupJoin
通過分組將兩個序列連接在壹起。
加入
從內部連接兩個序列。
分類
OrderBy
按值以升序對序列進行排序。
order by降序
按值降序排列序列。
然後呢
按升序對排序後的序列進行排序。
然後遞減
按降序對排序後的序列進行排序。
反面的
顛倒序列中項目的順序。
劃分
跳躍
返回跳過指定數量項目的序列。
滑雪時
返回跳過不滿足表達式的項的序列。
拿
返回具有指定項數的序列。
抓緊時間
返回包含滿足表達式的項的序列。
項目
挑選
創建部分序列的投影
選擇許多
創建部分序列的壹對多投影
預選賽
全部
確定序列中的所有項目是否滿足特定條件。
任何的
確定序列中是否有任何項滿足條件。
包含
確定序列是否包含指定的項。
限制
在哪裏
過濾序列中的項目
建立
明顯的
返回壹系列不重復的項目。
除...之外
返回表示兩個序列的差集的序列。
橫斷
返回表示兩個序列交集的序列。
聯盟
返回表示兩個序列交集的序列。
λ表達式
在對序列執行操作時,許多標準查詢運算符使用Func委托來處理單個元素。Lambda表達式可以與標準查詢運算符結合使用來表示委托。Lambda表達式是創建委托實現的簡短形式,可用於匿名委托適用的所有情況。C#和Visual Basic?。NET都支持Lambda表達式。但是,必須指出的是,由於Visual Basic。NET尚不支持匿名方法,Lambda表達式可能只包含壹條語句。
上例中的過程與下面的過程等效。
圖2.3 lambda表達式的使用
2.2 NHibernate
說到NHibernate,我們不得不提到Hibernate,原因很簡單,Hibernate是。NET版的Hibernate。
Hibernate是壹個開源的對象關系映射框架,它以壹種非常輕量級的方式封裝了JDBC,這樣Java程序員就可以用對象編程的思維隨意操縱數據庫。Hibernate可以在任何使用JDBC的情況下使用,不僅是在Java客戶端程序中,也可以在Servlet/JSP Web應用程序中使用。最具革命性的是,在應用EJB的J2EE架構中,Hibernate可以代替CMP,完成數據持久化的任務。
作為。NET的Hibernate,n Hibernate對Hibernate的應用完全壹樣,學習NHibernate可以直接學習Hibernate的資料。
事實上,雖然Hibernate是Java數據庫映射領域使用最廣泛的方案,但是NHibernate在。NET由於使用了映射方案,如LINQ(包括微軟的下壹代重量級實體框架)。
NHibernate需要配置數據庫配置文件和類/表映射配置文件,所以使用NHibernate需要了解XML文件的基礎知識,還需要掌握更復雜的XML文件配置節和相應的配置命令。
2.2.1數據庫配置文件
NHibernate官方提供了模板和配置文件示例供我們參考。
圖2.4 NHibernate官方數據庫配置文件模板(對應不同數據庫)
上圖是數據庫配置文件。“cfg.xml”通常用作後綴,壹個例子的文件內容如下。
圖2.5數據庫配置文件示例
下面是其他壹些可以改變NHibernate運行時行為的配置。所有這些都是可選的,並且有合理的默認值。
表2.2 NHibernate配置屬性
屬性名
使用
hibernate .方言
NHibernate中方言的類名——允許NHibernate使用某些數據庫平臺的特性。
例如:full.classname.of.Dialect(如果方言是在NHibernate中創建的),或者full。classname.of.dialect,assembly(如果使用自定義方言實現,則不屬於NHibernate)。
hibernate.default _架構
在生成的SQL中,scheml/表空間的完全限定名。
例如:模式名
hibernate.prepare_sql
要不要準備sql語句?
示例:真|假
hibernate .會話工廠名稱
SessionFactory將在創建後自動綁定此名稱。
例如:some.name
hibernate.use_outer_join
允許使用外部鏈接抓取。
示例:真|假
hibernate.cache.provider_class
指定自定義CacheProvider緩存提供程序的類名。
例如:full . class name . of . cache provider(如果ICacheProvider是在NHibernate中創建的),或者full . class name . of . cache provider,assembly(如果使用自定義ICacheProvider,則不屬於NHibernate)。
hibernate.query .替換
用SQL短語替換NHibernate查詢中的壹些短語(例如,短語可能是函數或字符)。
例如:hqlliteral = SQL _ literal,hqlfunction = sqlfunc。
實體映射配置文件
NHibernate官方開源包中提供了壹個實體映射配置文件的例子,供我們參考。
圖2.6 NHibernate開源包中提供的實體映射配置文件
和數據庫配置文件壹樣,實體映射配置文件也是壹個XML文件(XML真的很強大,微軟的下壹代應用開發技術WPF用XML文件把兩個長期脫離C/S和B/S的人統壹在壹個屋檐下),但不同的是,實體映射配置文件的後綴是“hbm.xml”。
圖2.7實體映射配置文件
要在實體映射配置文件中配置的信息通常是
(計劃或理論的)綱要
所有XML映射都需要使用nhibernate-mapping-2.0模式。當前模式可以在NHibernate的資源路徑或NHibernate.dll的嵌入資源中找到。NHibernate總是優先考慮資源中嵌入的模式文件。
休眠-映射
(1)
Schema(可選):數據庫模式名稱。
(2)
Default-cascade(可選-默認值為none):默認級聯樣式。
(3)
Auto-import(可選-默認情況下為true):指定我們是否可以在查詢語言中使用非限定類名(僅限此映射文件中的類)。
(4)
Default-access(可選-默認為property):NHibernate訪問屬性值時的策略。
(5)
Assembly(可選):指定壹個程序集,如果在映射文檔中沒有指定程序集,將使用該程序集。
(6)
Namespace(可選):指定壹個名稱空間前綴,如果在映射文檔中沒有指定完全限定名,將使用該前綴。
類(1)
Name:持久類(或接口)的完全限定名。
(2)
Table:對應的數據庫表名。
(3)
Discriminator-value(可選-默認情況下與類名相同):用於區分不同子類的值,用於多態行為。
(4)
Mutable(可選,默認為true):表示該類的實例是可變的(不可變的)。
(5)
模式(可選):在根處覆蓋
(6)
Proxy(可選):指定在延遲加載的情況下用作代理的接口。妳可以在這裏用妳自己的名字。
(7)
Dynamic-UPDATE(可選,缺省值為false):為UPDATE指定的SQL將在運行時動態生成,只有那些更改過的字段才會被更新。
(8)
Dynamic-INSERT(可選,默認為false):為INSERT指定的SQL將在運行時動態生成,並且只包括那些具有非空值的字段。
(9)
多態(可選,默認為隱式):定義查詢多態是隱式使用還是顯式使用。
(10)
Where(可選)指定壹個附加的SQL WHERE條件,該條件將在獲取該類的對象時添加。
(11)
Persister(可選):指定壹個自定義的IClassPersister。
(12)
Lazy(可選):如果設置了lazy="true ",則是將這個類的名稱設置為代理接口的等價快捷形式。
身份證(1)
名稱(可選):標識屬性的名稱。
(2)
Type(可選):標識NHibernate類型的名稱。
(3)
Column(可選-默認為屬性名):主鍵字段的名稱。
(4)
Unsaved-value(缺省情況下可選-null):壹個特定的標識屬性值,表示該實例剛剛創建,尚未保存。這可以將此類實例與那些已從先前會話加載但尚未再次持久化的實例區分開。
(5)
Access(可選-默認為property):NHibernate用來訪問屬性值的策略。
此外,我們還可以通過其他渠道了解更多的配置知識。對於壹個NHibernate項目,配置文件中的錯誤往往會導致錯誤的結果,甚至使程序無法運行。
3摘要
本文介紹了LINQ轉SQL和NHibernate,其中NHibernate用的篇幅比較多,因為相比LINQ轉SQL,NHibernate的入門門檻更高,配置也更復雜。LINQ轉SQL和NHibernate的優缺點會在後面的文章中討論,但其實由此得出了壹點,就是LINQ轉SQL比NHibernate好用,節省了人員培養的成本。