通用性站点管理后台(Bee OPOA Platform) (4)- DAL
该篇将介绍一下该平台中数据库访问层。设计之初考虑的主要偏向于方便应用, 由此数据访问层支持
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动态生成接口(一个接口的实现)实现的。