淺談Orm框架XCode v3.5源碼發布
淺談Orm框架XCode v3.5源碼發布是本文要介紹的內容,這段時間從我們各個系統抽取了基礎的常用的部分,整理后形成了一個XCode示例項目,包含三部分:DLL引用程序集、Web網站、YWS實體類庫。
之前發布了一些介紹XCode的文章,有些朋友希望能得到源碼,更多的朋友是想知道怎么用,想試一試!我們現有的系統是一個大體系,分割開來無法獨立工作,所以一直沒有提供XCode的例子項目。現在整理的這個例子項目,用到了XCode中常用的70%功能,蘊含著XCode開發模式的思想,希望能加深大家對XCode的了解。
XCode v3.5源碼(及相關組件、例子、代碼生成器等)目前存放于CodePlex,地址:http://xcode.codeplex.com/
充血模型,我們把它做得極其的大,所以才有了很多看似不可能的功能,我們不知道對與錯,至少這么多年都走過來了(本文后面附上XCode開發日志,見證了XCode的風風雨雨)。
其中的泛型基類,很多朋友看起來都覺得很暈
- /// <summary>
- /// 管理員
- /// </summary>
- /// <typeparam name="TEntity">管理員實體類</typeparam>
- /// <typeparam name="TRoleEntity">角色實體類</typeparam>
- /// <typeparam name="TMenuEntity">菜單實體類</typeparam>
- /// <typeparam name="TRoleMenuEntity">角色菜單實體類</typeparam>
- /// <typeparam name="TLogEntity">日志實體類</typeparam>
- public partial class Administrator<TEntity, TRoleEntity, TMenuEntity, TRoleMenuEntity, TLogEntity> : Administrator<TEntity>
- where TEntity : Administrator<TEntity, TRoleEntity, TMenuEntity, TRoleMenuEntity, TLogEntity>, new()
- where TRoleEntity : Role<TRoleEntity, TMenuEntity, TRoleMenuEntity>, new()
- where TMenuEntity : Menu<TMenuEntity>, new()
- where TRoleMenuEntity : RoleMenu<TRoleMenuEntity>, new()
- where TLogEntity : Log<TLogEntity>, new()
- {
這個泛型類帶有五個泛型參數,而每一個泛型參數都有相應的約束,所繼承的基類本身也是泛型類。這種泛型的設計方式,讓我們能夠抽象大量公共操作。當然,面向對象中的抽象和虛擬也可以抽象,但是我們這里通過泛型基類,還可以抽象靜態方法的實現,這也是我們大量使用泛型基類的原因。
有時候為了方便,會用一點匿名函數,如果匿名函數里面再用匿名函數,就會讓人發瘋,如果匿名函數再跟泛型混起來使用,那是……
- /// <summary>
- /// 擁有權限的菜單
- /// </summary>
- [XmlIgnore]
- public virtual EntityList<TMenuEntity> MenuList
- {
- get
- {
- return GetExtend<TMenuEntity, EntityList<TMenuEntity>>("MenuList", delegate
- {
- EntityList<TMenuEntity> list = EntityList<TMenuEntity>.From<TRoleMenuEntity>(Menus, delegate(TRoleMenuEntity item)
- {
- return Menu<TMenuEntity>.FindByID(item.MenuID);
- });
- if (list != null) list.Sort(Menu<TMenuEntity>._.Sort, true);
- return list;
- });
- }
- set { Extends["MenuList"] = value; }
- }
以上舉了XCode開發模式中兩個很特別的地方。(這年頭,我們追求各家之長,大家都有的就不拿出來現啦!)
下面我們看看這個例子項目都有哪些亮點
1、自動創建數據庫、數據表,這是XCode自身支持的功能。XCode有一個設置DatabaseSchema_Enable,打開后,每次啟動網站,都將檢查表結構,如果數據庫或者數據表不存在,將會根據實體類信息自動創建,如果數據表結構不一致,將會自動修改。目前支持Access、SQLite和MSSQL,其中MSSQL支持最完善,其它Oracle和MySQL等,隨著版本升級,很久沒有測試過。
而創建什么數據庫,Access、SQLite還是MSSQL,由連接字符串覺得,XCode所要做的第一個工作就是檢查現在的連接字符串對應著哪一種數據庫,以及版本(MSSQL中很重要)。在這里,XCode的任務就是構造一個適合系統工作的數據庫環境!
2、自動初始化數據。該功能由通用實體類組件CommonEntity實現。比如管理員實體類,在實體類的靜態構造函數中,檢查管理員表的數據,如果數據行數為0,表明沒有任何數據,這個時候,代碼將創建一個用戶名和密碼都是admin的默認管理員,并寫入數據表。其它的還有角色、菜單、權限等初始化。配合上面第一個功能,這種設計讓系統的部署變得非常簡單。只要配置好連接字符串,告訴系統你要用什么數據庫,系統將會為你完成一切數據庫部署工作。
看看初始化之后的系統
3、樹形實體。菜單和權限頁面的樹形結構,有幾個特點:沒有使用路徑字段,只有簡單的ParentID字段;菜單互相嵌套不會死循環,使用棧代替遞歸構造菜單樹;不會大量讀取數據庫,因為有實體緩存,不僅緩存了每一個實體,還緩存了整顆樹。頁面上沒有太多的實現代碼,甚至在通用實體類組件里面的菜單基類,也沒有太多的代碼,因為菜單基類也是繼承自樹形實體基類EntityTree,后面的客戶類別屬于樹形實體,也是繼承自它。
4、模版生成。很多頁面都是在模版生成的基礎上稍作修改,風格統一。
XCode例子項目會持續更新,可以從QQ群(10193406)的SVN上拿到最新的源碼,我們也會定期發布到CodePlex上!
XCode v3.5源碼(及相關組件、例子、代碼生成器等)目前存放于CodePlex,地址:http://xcode.codeplex.com/
附(XCode版本日志):
- /*
- * XCode的重大改進
- *
- * v6.0 增強的緩存和擴展屬性支持
- * v5.0 弱類型支持
- * v4.0 實體集合和緩存
- * v3.0 增加ORM的各種細節支持
- * v2.0 數據架構功能,實體和數據結構雙向映射
- * v1.2 使用泛型基類
- * v1.0 創建XCode
- * /
- /*
- * v6.5.2010.1223 修正SQLite已知的一些問題,查找dll文件路徑不正確,執行插入語句不正確
- * IEntity增加CopyFrom方法,用于從指定實體對象復制成員數據
- * 增加對二進制字段的支持,表現為Byte[]
- *
- * v6.4.2010.1217 修正Entity中CheckColumn無法正確計算選擇字段的錯誤
- * 優化SelectBuilder,允許Where中使用GroupBy字句,ToString時自動分割到正確位置
- * 實體類增加靜態方法FindByKeyForEdit,用于替代模版生成中的FindByKeyForEdit,為將要實現的表單基類(自定義表單)做準備
- * ********************************
- * 實體基類繼承自BinaryAccessor,IEntity增加IIndexAccessor接口和IBinaryAccessor接口,增加對快速索引訪問和二進制訪問的支持
- * 快速索引訪問:實體類可以不必生成索引器代碼,IIndexAccessor直接提供按名稱訪問屬性
- * 二進制訪問:支持把實體對象序列化成二進制或者反向操作
- * 這兩個功能尚未經過嚴格測試,請不要用于正式系統使用!
- *
- * v6.3.2010.1209 修正實體工廠EntityFactory緩存實體導致無法識別后加載實體程序集的錯誤
- *
- * v6.2.2010.1202 SQLite增加讀寫鎖,限制同時只能指定一個Excute操作
- * Entity的PageSplitSQL方法修正表名沒有進行格式化的BUG
- *
- * v6.1.2010.1119 取消依賴XLog,升級為依賴NewLife.Core,部分公共類庫移植到NewLife.Core
- * 修正EntityTree中FindChilds錯誤,增加排序字段的支持,如果指定排序字段,查詢子級的時候講按排序字段降序排序
- * 取消授權限制,但仍然混淆代碼
- *
- * v6.0.2010.1021 增加字典緩存DictionaryCache
- * 增加弱引用泛型WeakReference<T>
- * 單對象實體緩存改為弱引用,使得緩存對象在沒有引用時得到回收
- * 單對象實體緩存默認填充方法改為實體基類的FindByKey(前面某個版本增加,參數為Object),據說Delegate.CreateDelegate出來的委托會很慢
- * 實體元數據類Meta增加單對象實體緩存SingleCache,給SingleCacheInt和SingleCacheStr加上過期標識,到v7.0將不再支持
- * 實體元數據類Meta增加OnDataChange的數據改變事件,并使用弱引用,當該實體有數據改變后,觸發事件,可用于在外部清楚該對象的緩存
- * (重要更新)實體基類增加字典緩存Extends,用于存儲擴展屬性,并增加專屬的GetExtend方法用于獲取擴展屬性,向依賴實體類注冊數據更改事件
- * (重要更新)實體樹類升級為實體樹基類,所有具有樹形結構數據的實體類,繼承自該類,享受樹形實體的各種功能
- * 實體基類增加虛擬的CreateXmlSerializer,允許實體類重載以改變Xml序列化行為,默認序列化行為改為序列化為特性
- * EntityList改變序列化行為,默認序列化為特性
- * EntityList判斷元素是否存在Contains方法改為Exists
- * EntityList增加多字段排序方法Sort,可用于多個字段排序
- * 修復快速訪問方法、屬性和字段所存在的問題,在實體基類索引器使用
- *
- * v5.9.2010.1020 修正Database中QueryCountFast的嚴重錯誤
- *
- * v5.8.2010.1018 增加實體樹接口IEntityTree,用于解決實體樹操作的一些共性問題,避免死循環
- *
- * v5.7.2010.0930 XField中增加一個Table屬性指向自己的XTable,創建XField時必須指定所屬XTable
- * 增加只讀列表,各配置項使用只讀列表返回,配置項自身檢測列表是否被修改
- * 實體操作接口增加Fields和FieldNames屬性
- *
- * v5.6.2010.0909 修改DAL,把QueryTimes和ExecuteTimes改為本線程的查詢次數和執行次數
- * 修改Entity,Meta.Count返回表的總記錄數(快速),FindCount()使用普通方法查詢真實記錄數
- *
- * v5.5.2010.0903 實體操作接口IEntityOperate返回的實體集合改為EntityList<IEntity>,因為使用操作接口時一般不知道具體類型,如果知道就沒必要使用操作接口
- * 增加數據連接名映射的配置,允許通過配置修改某一個實體或者某一個連接名實際對應的連接名
- * 修改實體緩存和單對象緩存,使得緩存的數據因連接名或表名不同而不同,避免不同連接名或表名時緩存串號的問題
- * 修改實體類結構模型,比如Area:Area<Area>:Entity<Area>,使得實體類可以通過繼承實現二次擴展
- *
- * v5.4.2010.0830 數據架構中的異步檢查BeginCheck當啟用檢查時改為同步檢查Check,保證數據庫操作前先完成一次數據架構檢查
- * 唯一鍵為自增且參數小于等于0時,返回空
- * 實體操作接口IEntityOperate增加ToList方法,實現把ICollection轉為List<IEntity>
- * 優化Entity的FindAll方法,處理海量數據尾頁查詢時使用優化算法
- *
- * v5.3.2010.0826 DAL增加CreateOperate方法,為數據表動態創建實體類操作接口,支持在沒有實體類的情況下操作數據庫
- * 該版本為不穩定版本
- *
- * v5.2.2010.0726 IEntity接口增加SetItem方法,提供影響臟數據的弱類型數據設置
- * IEntityOperate接口增加Create方法,提供創建被類型實體對象的功能
- *
- * v5.1.2010.0709 增加實體接口、實體操作接口、實體基類的基類,提供弱類型的Orm支持
- *
- * v5.0.2010.0625 DAL優化
- * 重新啟用授權管理
- * EntityList增加排序方法Sort
- *
- * v4.9.2010.0430 使用SelectBuilder來構造SQL語句,用于各層之間傳遞,準備將所有方法往SelectBuilder過度。該更新可能造成使用GroupBy的地方計算出錯
- *
- * v4.8.2010.0325 修改Entity索引器,新的快速調用方法在set的時候有問題
- * 增加常用查詢方法為Web方法
- *
- * v4.8.2010.0301 增加實體類多表支持和多數據庫支持
- * 暴露幾個常用的實體類靜態方法供WebService引用
- *
- * v4.7.2010.0130 數據架構中識別表名時不應該區分大小寫
- * Entity中增加MakeCondition方法,以便于構造where語句
- *
- * v4.6.2009.1226 改善分頁算法,產生更簡單的分頁語句
- *
- * v4.5.2009.1127 增加單實體緩存
- *
- * v4.4.2009.1125 修改二級緩存,Entities改為EntityList類型,非空,支持FindAll操作
- *
- * v4.3.2009.1121 修正Entity中Save方法判斷自增字段不準確的BUG
- *
- * v4.2.2009.1114 優化SqlServer取架構信息的性能,以及輸出的SQL的可讀性
- * 支持Sql2008,通過Sql2005類
- * 優化QueryCount方法,產生更簡短的SQL
- *
- * v4.1.2009.1028 增加快速獲取單表總記錄數方法QueryCountFast,修改Entity,在記錄數大于1000時自動使用快速取總記錄數
- *
- * v4.0.2009.1011 增加實體類集合EntityList,Entity的所有FindAll返回EntityList
- * 增強數據架構功能,支持Access、SQL2000、SQL2005
- *
- * v3.7.2009.0907 修正DatabaseSchema中的一個小錯誤
- *
- * v3.6.2009.0819 修正FindCount方法的錯誤
- *
- * v3.5.2009.0714 Config類輸出的FieldItem集合改為數組,防止被外部修改。
- * 所有Select語句,使用*表示所有列,而不是列出所有列名。
- *
- * v3.4.2009.0701 修正SqlServer 2000取主鍵的錯誤
- *
- * v3.3.2009.0628 修改DAL,屏蔽Web請求級緩存DB的方法,似乎Web下多線程很不穩定,從而導致事務無法正常使用。
- *
- * v3.2.2009.0623 修改Oracle,重載GetTables方法,修正無法從Oracle數據庫取得構架信息的錯誤
- *
- * v3.1.2009.0611 修改SqlServer類,使得每次返回構架信息時,都是從數據庫取值。
- *
- * v3.0.2009.0608 元數據類Meta增加一個字段名列表屬性FieldNames
- * 調整DatabaseSchema類,新增字段時,直接設置默認值,否則對于非空字段,創建字段將會失敗
- * 數據構架增加DatabaseSchema_Exclude配置項,用于指定要排除檢查的鏈接名。
- * Entity中,增加ToXml輸出的Xml的編碼為UTF8,增加FromXml反序列化,增加Clone方法和CloneEntity方法
- * Database中,增加事務計數字段,支持多級事務。
- * Entity中,集合運算返回值改為List<T>,而不是IList<T>,更方便調用
- * 在Database的QueryCount方法增加自動去除排序子句的功能
- * Entity中,增加ToString重載,默認顯示Name屬性
- * Entity中,Update時,增加了臟數據的判斷,非臟數據的字段不更新,由于該功能的增加將導致以前所有的實體都無法Update到數據庫,故版本改為3.0
- *
- * v2.3.2009.0530 修正非自增字段做主鍵時也調用InsertAndGetIdentity的錯誤。
- *
- * v2.2.2009.0527 數據表結構中,增加Int16和Int64兩種類型
- *
- * v2.1.2009.0408 修正DAL中_DBs空引用的問題,可能是因為該成員是線程靜態,并沒有在每一個線程上new一個對象。
- *
- * v2.0.2009.0408 增加數據架構的功能。數據架構可以實現通過實體類反向更新數據庫結構,不啟用時,僅把更新SQL寫入日志
- * 修正Access類使用當前目錄時拼接路徑的錯誤。
- *
- * v1.2.2008.01.01 使用泛型基類重構
- *
- * v1.1.2007.03.08 大量擴展功能,支持自定義表單、廣義單點登錄等項目
- * 完善對Oracle的支持,支持電力生產管理系統等項目
- * 完善對Sybase的支持,支持電力SCADA數據分析等項目
- *
- * v1.0.2005.10.01 創建項目
- * 支持C++客戶端網絡驗證系統等項目
- * 支持圖片驗證碼識別等項目
- */
小結:淺談Orm框架XCode v3.5源碼發布的內容介紹完了,希望本文對你有所幫助!