最近在研究ORM,究竟什么樣的框架才是我們想要的
開發框架的意義在於
- 開發更標准,更統一,不會因為不同人寫的代碼不一樣
- 開發效率更高,無需重新造輪子,重復無用的代碼,同時簡化開發流程
- 運行效率得到控制,程序穩定性得到提高
把網上關注比較多的框架搜了搜,作了個列表
- Nhibernate
來源於Java的Hibernate
參考:http://www.cnblogs.com/ylwn817/articles/1963528.html - Entity Framework
微軟本家框架,都比較熟悉 - iBATIS.NET
apache開源項目
參考:http://developer.51cto.com/art/200907/137796.htm - Nbear
博客園Teddy開發的項目
參考:http://www.cnblogs.com/teddyma/archive/2006/11/07/553562.html - Castle ActiveRecord
ActiveRecord是Hibernate的一個延伸
參考:http://terrylee.cnblogs.com/archive/2006/04/03/365762.html
加再上其他人寫的一些框架,包括自已寫的,大差不差
整理了一些常用的特性,對這些框架作一個評分
- 可編程性(語法支持) 我們希望不再用字符串的形式拼接SQL,並且能通過編譯驗證
- 容錯性 可看作是上面擴充,不希望一個地方改了,其它地方沒改,沒任何提示,造成錯誤
- 開發效率 包括框架的配置,開發過程
- 關聯查詢支持度 關聯查詢是不可避免的
- 額外配置 是否需要額外配置和第三方工具支持,影響開發效率
- 緩存支持 能大大增強程序效率
跟數據庫打交道,最重要的功能當屬查詢了,查詢做得好不好直接影響易用度,Lambda和Linq方式為首選
下面是對這些框架的分析,沒有仔細研究,可能不對,只代表個人意見,僅供參考
Nhibernate
新版Nhibernate增加了Lambda和Linq查詢支持
Join好像也能實現了
var list1 = session.CreateCriteria<Product>() .Add(Restrictions.Eq("Discontinued", false)) .Add(Restrictions.Eq("Category.Id", 2)) .List<Product>();
對緩存支持也有,有多種實現方式
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html
只是一如既往需要配置XML映射
Entity Framework
在上述特性中,除了沒有緩存,EF都比較完美,關且在最新版7中,強制了CodeFirst模式,是其它框架沒有的(這樣更符合業務開發模式)
有的說EF太過龐大,用不好效率會有些問題,確實,特別是關聯,寫不好就弄出沒效率的SQL語句,這也正是他可編程性太強的緣故,如果不是這么強,就不會這么寫,會想想把結構好好設計設計
由於太過於對象的概念,默認不支持批量更新/刪除
iBATIS.NET
除了有基本的對象映射優點只剩靈活來描述了,所有操作都需要配置XML文件來表示
﹤select id="GetAllAccountsAsHashMapViaResultMap" resultMap="account-hashtable-result"﹥ select * from Accounts order by Account_ID ﹤/select﹥
好像還支持緩存
﹤select id="GetCachedAccountsViaResultMap" resultMap="account-result" cacheModel="account-cache" ﹥ select * from Accounts order by Account_ID ﹤/select﹥
這已經不屬於面向對象,就是一個查詢映射
Nbear
Nbear可以通過對象的方式自動映射對象關聯,但不能直接關聯查詢
條件查詢,參數化,不太智能,好像好長時間沒更新了,不知現在是怎么查
LocalUser[] users = gateway.Select<LocalUser>(_Entity.LocalUser.Id > 5 | _Entity.LocalUser.LoginId == "teddy", _Entity.LocalUser.Id.Desc & _Entity.LocalUser.LoginId.Asc);
可以使用配置的方式支持緩存,好像只能單個表
<cacheConfig enable="true"> <cachingTables> <add key="Northwind.Orders" value="5" /> </cachingTables> </cacheConfig>
除了表映射外,還支持視圖,存儲過程映射,(這個其實已經脫離面向對象的概念了,設計好的業務對象,對這基本沒需求)
對象定義是接口類型,不明白
public interface IdentableEntity : IEntity { [PrimaryKey] int Id { get; set; } string Name { get; set; } }
Castle ActiveRecord
ActiveRecord延伸於hibernate,少不了一堆數據庫配置
也支持關聯對象,通過屬性定義
[HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")] public IList Posts { get { return _posts; } set { _posts = value; } }
查詢方式為方法傳參,比較原始,不知最新的沒有引入Linq和Lambda
http://terrylee.cnblogs.com/archive/2006/04/12/372823.html
SimpleQuery query = new SimpleQuery(
typeof(Post),typeof(int),
@"select post.Id from Post post where post.Created between ? and ?",
start,end
);
綜合起來
可編程性(語法支持) | 容錯性 | 開發效率 | 關聯查詢支持度 | 額外配置 | 緩存支持 | |
Nhibernate | Linq&Lambda語法 | 高 | 中 | 中 | 映射需要配置XML | 支持 |
Entity Framework | Linq&Lambda語法 | 高 | 高 | 高 | 不支持 | |
iBATIS.NET | 無 | 低 | 低 | 高 | XML配置查詢 | 支持 |
Nbear | 運算符重載 | 高 | 中 | 中 | 需要工具生成類 | 支持 |
Castle ActiveRecord | 無 | 低 | 中 | 中 | 支持 |
查詢
在設計ORM框架時,來表示查詢一般分幾種情況
- 實現linq&Lambda語法糖,借助.NET框架實現表達式解析
- 自已寫表達式,實現類似的效果(代價是要借助工具生成一堆代理類,好多個人開發的框架都有這種弊病)
- 通過方法表示運算 如.BigThan("Number",">10") 這樣太復雜,可編程性差,容錯性低
- 直接SQL 這種會造成可編程性和容錯性低
可以看出最好的方式當屬Linq和Lambda了
更新
理想情況下,對象的哪個屬性修改了,就更新到哪個數據庫里,會有以下幾種設計
- 在屬性SET方法上做文章,以在值修改了知道是哪個屬性被更改了,更新時按此進行判斷
代價:需要大批量修改SET方法或用模版生成(EF7好像已經解決這個問題了) - 參過參數的形式賦值,缺點是不太智能,可編程性容錯性不高
- 采用AOP消息代理攔截屬性變動,這種效率太低,並且沒法調試
性能,緩存
雖然現在很少看到WEB服務器CPU占用很高,但運行效率還是需要考慮,運行邏輯判斷時間直接影響請求響應時間,在ORM框架
這個時間多消耗在類型與數據映射,要減少響應時間,需要對映射行為進行優化,減少不必要的計算
開發高效的應用程序少不了緩存的支持,數據不可能總是從數據庫讀取,也不總是非要進行關才才能獲得數據
緩存創建,過期處理,和查找效率也需要進行考慮,像Nhibernate和Nbear必須先進行配置才能緩存,簡值不能忍
CodeFirst Or DbFirst
上面也提到,EF7強制了CodeFirst模式,開發觀念要發生改變了,先業務后數據,數據是基於業務實現得來的,理想情況下
有什么樣的業務結構,就應該會有什么樣的數據表結構,不應去管數據庫是什么樣的,由框架來處理就行了,比如自動映射,自動創建維護數據庫
那種寫完對象結構還得再配個XML數據表映射文件的形為,得拖出去槍斃10分鍾
開發便捷性
好多框架需要用工具生成一堆代理類,增加屬性/字段了,再生成一遍,這樣便捷性很低,就像一輛賽車開跑前先得預熱10分鍾,很讓人着急
泛類型問題:對數據進行操作時,有的必須帶上泛類型,這樣在開發時感覺帶上了一個尾巴,很冗余,不方便
多種數據庫/多庫支持
多庫支持不可避免,這意味着框架能按業務進行配置使用哪個庫
在框架設計時基本會考慮多種數據庫支持,如果是多種數據庫多庫...
以上僅為個人觀點,不對的地方請指證