支持C#的分表分庫組件-Ctrip DAL
本文轉載自微信公眾號「后端Q」,作者conan。轉載本文請聯系后端Q公眾號。
簡介
Ctrip DAL是攜程框架部開發的數據庫訪問框架,支持代碼生成和水平擴展。其由攜程技術中心框架部DAL團隊開發,歷經3年不斷打磨,并在長期的實際使用中基于大量的用戶反饋不斷優化。
開源范圍包括代碼生成器,Java客戶端和C#客戶端。
背景
隨著企業規模擴張和業務量的急劇增加,作為系統核心的數據庫相關開發也會經歷一個由單一團隊發展為多團隊;由單機擴張到集群;由單數據庫發展為多數據庫;由采用單一數據庫產品到多種數據庫產品并存的過程。伴隨這一過程的是如何管理數據庫擴展,如何規范數據庫訪問,如何保護數據庫投資,如何應對訪問量增加,如何預防安全問題等一系列挑戰。作為中國在線旅游行業的翹楚,攜程也曾經面對同樣困擾。為了應對這些挑戰,實現企業10倍速發展,攜程開發了具有自己特色的數據庫訪問框架Ctrip DAL。
Ctrip DAL支持流行的分庫分表操作,支持Java和C#,支持Mysql和MS SqlServer。使用該框架可以在有效地保護企業已有數據庫投資的同時,迅速,可靠的為企業提供數據庫訪問層的橫向擴展能力。整個框架包括代碼生成器和客戶端。工作模式是使用代碼生成器在線生成代碼和配置,通過DAL客戶端完成數據庫操作。生成器具有豐富的向導指引,操作簡單清晰,即可以批量生成標準DAO,也可以在方法級別定制數據庫訪問。客戶端則可以簡單的通過標準的maven方式添加依賴。
Ctrip DAL與一般數據庫框架最大的不同是從企業跨部門的角度,統一管理數據庫相關資源。通過部署代碼生成器,企業可以做到有效的管理全公司的DAL開發團隊,明確數據庫歸屬和定制數據庫訪問。通過代碼生成器生成的標準DAO代碼與客戶端配合使用,可以大幅提高工作效率,保證代碼質量。解決了業內常見的伴隨業務成長而帶來的系統維護困難,開發效率低下,代碼風格五花八門,代碼質量參差不齊等痛點問題。
代碼生成器
代碼生成器允許用戶創建Dal團隊,組織開發人員,管理數據庫,創建DAO并生成代碼和配置。與一般基于JDBC driver的DB sharding產品不同的是,代碼生成器生成的代碼和配置可以直接拿來實用,完全無需用戶寫一行代碼和配置。做到了只需開發人員關心業務邏輯,而把繁瑣的數據庫相關的編碼和配置任務全部交給DAL。由于Ctrip DAL完全在DAO這層工作,也沒有什么這種SQL語句不支持,那種SQL語句不能用的情況。同時傳遞hints的方式也非常自然,每個方法都自帶hints的接口,需要DAL額外做什么可以直接按給定的已有名字來設置,無需改寫原始的sql來添加怪異的注釋。
客戶端簡介
客戶端配合代碼生成器生成的代碼來完成用戶的數據庫訪問操作。通過Dev和QA兩方面雙重自動化測試來保障質量,覆蓋率達到99%,并經過生產實際實用的的長期嚴格檢驗。為了適應不同公司的實際情況,DAL客戶端定義了豐富的擴展接口,覆蓋了從數據源管理,數據庫映射,連接串讀取到自定義訪問方式等等方方面面的功能。同時為了方便系統監控還內置了系統狀態,日志和統計模塊。
C#客戶端 API列表
以下這些API位于BaseDao類中 方法族說明:除了所示的方法之外,至少還包含一個帶有IDictionary hints參數的重載方法。
注意:增刪改均適用的API被歸類至Update系列
- Create
- Object Insert<T>(T obj) where T : class, new() 方法族
- Object InsertByComplexPk<T>(T obj) where T : class, new() 方法族
- Boolean BulkInsert<T>(IList<T> list) where T : class, new() 方法族
- Retrieve
- IQuery<T> GetQuery<T>() where T : class, new()
- IList<T> GetAll<T>() where T : class, new() 方法族
- IList<T> SelectListOfSingleField<T>(String sql) 方法族
- IList<T> SelectList<T>(String sql) where T : class, new() 方法族
- IList<T> SelectList<T>(IQuery query) where T : class, new() 方法族
- IList<T> SelectListByAdapter<T>(String sql) where T : class, new() 方法族
- IList<T> SelectListByAdapter<T>(IQuery query) where T : class, new() 方法族
- IList<T> ExecListBySp<T>(String procName, StatementParameterCollection parameters) where T : class, new() 方法族
- T GetByKey<T>(Object key) where T : class, new() 方法族
- T SelectFirst<T>(String sql) where T : class, new() 方法族
- T SelectFirst<T>(IQuery query) where T : class, new() 方法族
- T VisitDataReader<T>(String sql, Func<IDataReader, T> callback) 方法族
- T VisitDataReaderBySp<T>(String procName, StatementParameterCollection parameters, Func<IDataReader, T> callback) 方法族
- DataTable SelectDataTable(String sql) 方法族
- DataTable ExecDataTableBySp(String procName, StatementParameterCollection parameters) 方法族
- DataSet SelectDataSet(String sql) 方法族
- DataSet SelectDataSet<T>(IQuery query) where T : class, new() 方法族
- DataSet ExecDataSetBySp(String procName, StatementParameterCollection parameters) 方法族
- IDataReader SelectDataReader(String sql) 方法族
- IDataReader ExecDataReaderBySp(String procName, StatementParameterCollection parameters) 方法族
- Object ExecScalar(String sql) 方法族
- Object ExecScalarBySp(String procName, StatementParameterCollection parameters) 方法族
- Update
- Int32 Update<T>(T obj) where T : class, new() 方法族
- IUpdatePartial<T> GetUpdatePartially<T>() where T : class, new()
- Int32 UpdatePartially<T>(IUpdatePartial<T> partially, T obj) where T : class, new() 方法族
- Int32 ExecNonQuery(String sql) 方法族
- void ExecSp(String procName, StatementParameterCollection parameters) 方法族
- Delete
- Int32 Delete<T>(T obj) where T : class, new() 方法族
https://github.com/ctripcorp/dal