該篇將介紹一下該平台中數據庫訪問層。設計之初考慮的主要偏向於方便應用, 由此數據訪問層支持
1. 簡單, 方便, 高效。 API簡單高效。
2. 支持嵌套調用。 DbSession.Current
3. 通用。 支持主流數據庫應用。 已使用驗證過的包括Sqlite, SqlServer2008, SqlServer2005, Oracle。
DbSession的介紹
先來看一下DbSession的主要API。
/* 實現IDisposable接口, 推薦使用using方式*/ public sealed class DbSession : IDisposable { public DbSession(string connectionName) { /*使用配置文件中的連接名, 默認不啟用事務*/ } public DbSession(string connectionName, bool useTransaction) {/*使用配置文件中的連接名, 是否啟用事務*/ } /// <summary> /// 手動注冊連接字符串。 /// </summary> public static void Register(string connectionName, string providerName, string connectionString) { } public int CommandTimeout { get; set; }/* 該實例調用的超時時間*/ public static DbSession Current { get; /* 獲取當前上下文中DbSession實例, 不跨線程。 若上下文中未聲明過, 則使用配置文件中第一個連接。*/ } public void CommitTransaction() { /* 提交事務, 若不執行, 則自動rollback。 若中途拋異常, 自動rollback。*/ } public int Insert(string tableName, BeeDataAdapter dataAdapter) { /* 指定表名, 插入數據集。 若不是該表中的字段, 則自動忽略。*/ } public void Update(string tableName, BeeDataAdapter dataAdapter, SqlCriteria sqlCriteria) { /*指定表名, 數據集, 及條件集, 更新表*/ } public void Delete(string tableName, SqlCriteria sqlCriteria) { /*指定表名, 及條件集, 刪除數據*/ } public DataTable Query(string tableName, SqlCriteria sqlCriteria) { } public DataTable Query(string tableName, SqlCriteria sqlCriteria, string orderbyClause) { } public DataTable Query(string tableName, string selectClause, SqlCriteria sqlCriteria, string orderbyClause, int pageIndex, int pageSize, ref int recordCount) { } public DataTable ExecuteCommand(string cmdText, BeeDataAdapter dataAdapter) { } public List<T> ExecuteCommand<T>(string cmdText, BeeDataAdapter dataAdapter){} public int Insert<T>(T value) { }
public void Delete<T>(SqlCriteria sqlCriteria) { }
public int Save<T>(T value) { }
public List<T> Query<T>() { } public List<T> Query<T>(SqlCriteria sqlCriteria) { } public List<T> Query<T>(SqlCriteria sqlCriteria, string orderbyClause, int pageIndex, int pageSize, ref int recordCount) { } public DataTable CallSP(string spName, BeeDataAdapter dataAdapter) { /*調用存儲過程。 若數據中的參數不是該存儲過程的參數, 則自動忽略。 請注意存儲過程的參數列表被緩存。 */ } #region Schema Access /// <summary> /// 獲取所有Table, SP, View /// </summary> public List<DbObject> GetDbObject() { } public TableSchema GetTableSchema(string tableName) { } public SPSchema GetSpSchema(string spName) { } /// <summary> /// 根據表結構, 獲取創建表sql /// </summary> public string ToCreateTableScript(TableSchema tableSchema) { } /// <summary> /// 通過類型獲取表結構 /// </summary> public TableSchema GetEntitySchema(Type type) { } #endregion }
接口定義中, 大部分日常操作都能滿足。 該接口同時可以滿足獲取DataTable及Orm方式。
DbSesion的嵌套調用
嵌套應用還是比較常用的, 尤其是在分層系統應用中。 很多底層方法都是完成特定功能的, 如獲取單據號。 如下方法:
public string GetBillId(string billType) { string result = string.Empty; BillTypeConfig billTypeConfig = null; DbSession dbSession = DbSession.Current;
DateTime dateTime = DateTime.Today; string billDate = ""; // 當期, 如20121225, 201212. billTypeConfig = dbSession.Query<BillTypeConfig>( SqlCriteria.New.Equal("billtype", billType).Equal("billdate", billDate)).FirstOrDefault(); if (billTypeConfig == null) { billTypeConfig = new BillTypeConfig(); billTypeConfig.BillType = billType; billTypeConfig.BillDate = billDate; billTypeConfig.LastId = 1; } else { billTypeConfig.LastId = billTypeConfig.LastId + 1; } dbSession.Save(billTypeConfig); // 拼湊單據號 return result; }
如沒有上述代碼中紅色標注這一句, 一般實現要不就不管事務, 要不就需要將當前的訪問數據庫的上下文作為變量傳進來。 若用DbSession.Current處理該類情況, 則十分的優雅, 該方法會自動根據調用方的連接走, 無論是換個連接, 還是是否啟用事務。
簡單ORM實現
所有的泛型QueryAPI其實都是先獲取了DataTable后, 再進行ORM映射的。 之間的轉換也是通過Emit動態生成接口(一個接口的實現)實現的。