1、框架簡介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html
html
2、框架使用方式介紹 http://www.cnblogs.com/qixiaoyizhan/p/7418058.htmlgit
3、框架性能對比 近期補充程序員
ORM(Object Relational Mapping)框架採用元數據來描述對象一關係映射細節,框架根據對象之間的關係以及對象自身的屬性能夠框架內部自動生成sql語句,簡化了程序員的sql開發,極大地提高了編碼效率,同時也使得程序錯誤代碼的發生率下降,提升程序的可讀性,在使用上相較傳統的DAO Sql語句的寫法有極大的優點。github
任何優秀的新事物都是一把雙刃劍,有利就有弊,關鍵看使用這把劍的人如何去操做。不盡其然,ORM框架也是有碧如執行比較慢缺點,可是捨棄性能的同時提高開發效率,某些程度上也是能夠廣爲接受的,所以,ORM開發的重點又突出在了易使用和高性能兩個方面。web
今天,我這裏推出一款本人花費一週時間獨立開發的ORM框架:Bantina 初版sql
該框架採用特性的方式作數據表關係映射,吸納了Microsoft的EntityFramework的一些思想,而且簡化了EntityFramework的功能,同時極力向原生的sql語句靠攏,以提升程序執行效率。自帶緩存的支持提高查詢效率,做爲Bantina初版,咱們先暫時支持SqlServer數據庫的操做,在後續的版本升級中,逐步開放對Mysql、Oracle甚至是NoSql的支持。數據庫
下面咱們對Bantina 1.0 作詳細介紹。緩存
介紹以前,咱們先在本地建立一個數據庫,做爲演示使用實例以及數據庫查詢對比的操做對象,該數據庫結構以下圖所示:app
數據庫名:DB_QX_Frame_Test框架
其中包含三張表:TB_ClassName (班級名稱)
TB_People (人員表)
TB_Score (分數表)
表之間的關係是TB_People中有TB_ClassName的外鍵
咱們先對Bantina1.0 ORM框架支持的功能作列表介紹,突出框架封裝的簡單操做方法以及框架支持的簡介操做的特性。
數據庫實體類繼承自框架Bantina,而後在構造方法裏面提供數據庫鏈接字符串,有多種參數可供選擇。
1 public class DB_QX_Frame_Test : Bantina 2 { 3 public DB_QX_Frame_Test() : base("data source=.;initial catalog=DB_QX_Frame_Test;persist security info=True;user id=Sa;password=Sa123456;MultipleActiveResultSets=True;App=EntityFramework") { } 4 }
在數據庫初始化的同時,傳入的數據庫鏈接字符串能夠進行讀寫庫的分離設置,極大方便了數據庫讀寫分離的操做(框架原生支持讀寫分離)。
若是傳遞單條鏈接字符串,那麼讀寫庫使用一個,至關於關閉讀寫分離。
該特性沿襲了EntityFramework的特色,可是並不必定追求實體類必定要和數據庫結構徹底一致,不存在匹配一致性檢測,全部的數據庫表字段使用特性標籤的方式標記識別。
在主外鍵上,直接將外鍵表的屬性添加進主表便可,並添加標籤[ForeignTable]聲明外鍵表便可。
1 [Table(TableName = "TB_People")] 2 public class TB_People 3 { 4 [Key] 5 public Guid Uid { get; set; } 6 [Column] 7 public string Name { get; set; } 8 [Column] 9 public int Age { get; set; } 10 [Column] 11 [ForeignKey] 12 public int ClassId { get; set; } 13 [ForeignTable] 14 public TB_ClassName TB_ClassName { get; set; } 15 } 16 17 [Table(TableName = "TB_ClassName")] 18 public class TB_ClassName 19 { 20 // PK(identity) 21 [Key] 22 public Int32 ClassId { get; set; } 23 // 24 [Column] 25 public String ClassName { get; set; } 26 }
這裏標籤Table能夠支持數據庫的表名和實體類的表名不一致,在參數TableName聲明數據庫真實的表名便可。
在alpha版本里,字段也是支持修改並配置的,可是爲了支持後續的特性Lambda表達式參數,將此功能去掉,以便簡化框架代碼,所以,字段名稱是須要類屬性和表的字段徹底一致的狀況下進行操做的。
這裏字段的標籤Key以及Column也是有必要的,在後續的使用中會進行逐步講解。這裏你們可能會有疑問,每一個屬性手動寫標籤會比較多,比較麻煩,這裏有專門匹配的代碼生成器進行生成,避免了手動添加的繁瑣。
Sql查詢的耗時主要出如今大量數據的查詢上,一套系統若是沒有良好的設計,每次獲取數據都要進行大量耗時查詢操做,那麼系統的用戶體驗感將會降到極低,直接影響到了用戶的使用心情。
Bantina框架原生自帶了緩存特性,在對數據庫的查詢操做時,並不會直接對全部數據進行緩存,只會對當前的查詢操做執行的結果進行緩存,當對操做的表進行增刪改操做時,又會智能識別下次從新獲取數據並覆蓋緩存。這樣避免了全表數據緩存查詢的耗時時間,又能在數據查詢的緩存支持上獲得很好的效率。
緩存的智能消除,極力維護了系統數據一致性,避免了等待緩存過時形成的數據尷尬問題。
這裏查詢同一組集合數據的三段一樣的代碼耗時展現(單位:毫秒):
能夠看出,第一次是從數據庫進行獲取數據,並添加到緩存,第二次和第三次是從緩存中獲取的數據,速度很是快;
原生支持各類經常使用查詢結果,不須要後續進行遍歷等格式轉化操做,一切以對象及集合說話,徹底符合面向對象行爲方式。
這裏的Query查詢方法包含了Entity<T>單個實體對象的查詢以及Entities<T>多個實體對象List列表的查詢。
1 TEntity QueryEntity<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 2 List<TEntity> QueryEntities<TEntity>() where TEntity : class; 3 List<TEntity> QueryEntities<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class;
這裏我展現Bantina經常使用的方法接口:
1 public interface IBantina 2 { 3 Task<bool> Add<TEntity>(TEntity entity) where TEntity : class; 4 Task<bool> Update<TEntity>(TEntity entity) where TEntity : class; 5 Task<bool> Update<TEntity>(TEntity entity, Expression<Func<TEntity, bool>> where) where TEntity : class; 6 Task<bool> Delete<TEntity>(TEntity entity) where TEntity : class; 7 Task<bool> Delete<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 8 bool QueryExist<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 9 int QueryCount<TEntity>() where TEntity : class; 10 int QueryCount<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 11 TEntity QueryEntity<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 12 List<TEntity> QueryEntities<TEntity>() where TEntity : class; 13 List<TEntity> QueryEntities<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class; 14 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, bool isDESC = false) where TEntity : class; 15 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, bool isDESC = false) where TEntity : class; 16 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, out int count, bool isDESC = false) where TEntity : class; 17 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, out int count, bool isDESC = false) where TEntity : class; 18 DataTable QueryDataTable<TEntity>(string sql, params SqlParameter[] parms) where TEntity : class; 19 DataSet QueryDataDataSet<TEntity>(string sql, params SqlParameter[] parms) where TEntity : class; 20 int ExecuteSql<TEntity>(string sql, params SqlParameter[] parms) where TEntity : class; 21 List<TEntity> ExecuteSqlToList<TEntity>(string sql, params SqlParameter[] parms) where TEntity : class; 22 int ExecuteStoredProcedure<TEntity>(string storedProcedureName, params object[] parms) where TEntity : class; 23 List<TEntity> ExecuteStoredProcedureToList<TEntity>(string storedProcedureName, params object[] parms) where TEntity : class; 24 }
數據庫的查詢自帶分頁查詢方法,不須要咱們後續進行查所有集合後的分頁操做,極大地提高了開發的效率。
分頁的條件完整全面且易於傳遞及操做,對程序員的開發有較大的幫助。
1 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, bool isDESC = false) where TEntity : class; 2 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, bool isDESC = false) where TEntity : class; 3 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, out int count, bool isDESC = false) where TEntity : class; 4 List<TEntity> QueryEntitiesPaging<TEntity, TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, out int count, bool isDESC = false) where TEntity : class;
對數據集合的查詢條件所有統一使用Lambda表達式,便於操做的同時,極大下降了手動拼寫錯誤的風險。
這裏的Lambda表達式徹底使用標準的Linq風格,在Lambda的支持條件下,查詢條件對String類型的字段默認支持一下幾種篩選條件:
t.Equals(""); //徹底匹配
t.Contains(""); //模糊查詢
t.StartWith(""); //模糊查詢起始字符固定
t.EndsWith(""); //模糊查詢結束字符固定
...
例如咱們須要查詢People表Name字段包含2的全部數據的數目,操做方法以下圖所示:
Bantina在提倡框架風格使用的基礎上,也提供了對原生SQL語句和存儲過程執行的支持,便於適應多變的生產環境。
Bantina的增刪改操做所有采用異步Task線程執行的方式,提升了程序的執行效率。
在多行數據的批量添加修改刪除循環調用的時候,會提高插入操做執行的效率。
默認對異步的支持,也可使得web服務的響應獲得提高,間接提升了用戶體驗感。
1 Task<bool> Add<TEntity>(TEntity entity) where TEntity : class; 2 Task<bool> Update<TEntity>(TEntity entity) where TEntity : class; 3 Task<bool> Update<TEntity>(TEntity entity, Expression<Func<TEntity, bool>> where) where TEntity : class; 4 Task<bool> Delete<TEntity>(TEntity entity) where TEntity : class; 5 Task<bool> Delete<TEntity>(Expression<Func<TEntity, bool>> where) where TEntity : class;
Bantina框架封裝了對事務的支持,並且調用很是簡潔。
只須要數據庫上下文對象調用事務方法,而後傳遞一個委託給方法做爲參數執行委託事件便可。
下面我使用了匿名委託的方式進行調用事務執行操做,在委託方法裏面分別執行了幾組須要支持事務操做的數據庫操做,而後方法自動提交事務,若是有事務失敗的操做,那麼方法會自動回滾操做。
代碼展現以下圖所示:
Bantina能夠經過配置主外鍵關係,經過特定的特性標籤來標識主外鍵關係,而後達到主外鍵關聯查詢的目的。
配置代碼見該介紹第三條 三、特性標籤的方式標記實體類
例如咱們要支持關聯外鍵表TB_ClassName的查詢,並將班級的名稱顯示,經過配置後,咱們能夠進行以下查詢操做:
查詢結果以下圖所示:
Bantina實現瞭如上的關聯查詢操做方式。
介紹完咱們的Bantina框架後,咱們將在下一章對Bantina的使用方法進行介紹:
2、框架使用方式介紹 http://www.cnblogs.com/qixiaoyizhan/p/7418058.html
一、Nuget獲取:Nuget搜索 QX_Frame.Helper_DG
二、GitHub查看源代碼:https://github.com/dong666/QX_Frame.Helper_DG
注:bantina已正式更名爲Bankinate,新版本GitHub:https://github.com/dong666/QX_Frame.Bantina
三、聯繫本人獲取,聯繫方式在下方博客簽名中,qq、email都可。