本文希望能给大家一些启发。前言:这两天重温经典,对ADO.NET的东西稍微深入的了解了一下,顺便写点代码练练手,全当是复习笔记吧。
一、简单说说ADO.NET的5大常用对象
既然说ADO.NET,当然不能免俗地要提到5大常用对象。本文不会对ADO.NET的5大对象和它们的关系进行过多阐释,不过我们应该对下面这张图的结构有个了解:
关于上图图示中的5大对象,经常做以数据为驱动的mis系统的童鞋应该不会陌生。本文一笔带过。下面我们一步一步实现以ADO.NET为核心的数据访问程序。
二、数据访问持久化层
1、IDbOperation接口
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- namespace AdoNetDataAccess.Core.Contract
- {
- public interface IDbOperation
- {
- DbCommand CreateDbCommd(DbConnection sqlConn, DbTransaction transaction, string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- DbParameter CreateDbPrameter(string paramName, object paramValue);
- DbDataReader ExecuteReader(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- DataTable FillDataTable(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- DataSet FillDataSet(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- object ExecuteScalar(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- int ExecuteNonQuery(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- /// <summary>
- /// 批量插入
- /// </summary>
- /// <param name="tableName">表名称</param>
- /// <param name="dt">组装好的要批量导入的datatable</param>
- /// <returns></returns>
- bool ExecuteBatchInsert(string tableName, int batchSize, int copyTimeout, DataTable dt);
- void OpenConnection();
- void CloseConnection();
- }
- }
上面的接口包括增删改查,批量插入以及数据库连接对象的连接和关闭等常用操作,您可以根据命名和参数轻松理解函数的含义。根据楼猪的开发经验,对于平时的数据库操作,上述方法差不多够用了。当然您也可以按照自己需要,重写组织添加其他函数。
2、针对一种数据源的数据操作实现
底层的数据操作接口定义好后,就要针对一种数据源,具体实现上述的数据操作。这里楼猪选择了Sql Server。我们也可以实现其他数据源的数据访问操作,按照配置,利用抽象工厂动态反射选择是哪一种数据源的实现。这里按下不表,有心的童鞋自己可以动手一试。下面是具体的实现:
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- using System.Data.SqlClient;
- using System.Transactions;
- namespace AdoNetDataAccess.Core.Implement
- {
- using AdoNetDataAccess.Core.Contract;
- public class SqlServer : IDbOperation, IDisposable
- {
- private int cmdTimeOut = 60;
- private DbConnection sqlConn = null;
- private DbCommand cmd = null;
- private SqlServer()
- {
- }
- public SqlServer(string sqlConStr)
- {
- sqlConn = new SqlConnection(sqlConStr);
- cmdTimeOut = sqlConn.ConnectionTimeout;
- }
- public SqlServer(string sqlConStr, int timeOut)
- {
- sqlConn = new SqlConnection(sqlConStr);
- if (timeOut < 0)
- {
- timeOut = sqlConn.ConnectionTimeout;
- }
- cmdTimeOut = timeOut;
- }
- #region contract method
- public DbCommand CreateDbCommd(DbConnection sqlConn, DbTransaction transaction, string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- DbCommand cmd = new SqlCommand();
- cmd.Connection = sqlConn;
- cmd.CommandText = sqlStr;
- cmd.CommandType = cmdType;
- if (transaction != null)
- {
- cmd.Transaction = transaction;
- }
- if (listParams != null && listParams.Count > 0)
- {
- cmd.Parameters.AddRange(listParams.ToArray());
- }
- cmd.CommandTimeout = cmdTimeOut;
- OpenConnection();
- return cmd;
- }
- public DbParameter CreateDbPrameter(string paramName, object paramValue)
- {
- SqlParameter sp = new SqlParameter(paramName, paramValue);
- return sp;
- }
- public DbDataReader ExecuteReader(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- DbDataReader rdr = null;
- try
- {
- OpenConnection();
- cmd = CreateDbCommd(sqlConn, null, sqlStr, cmdType, listParams);
- rdr = cmd.ExecuteReader();
- }
- catch (Exception ex)
- {
- throw ex;
- }
- return rdr;
- }
- public DataTable FillDataTable(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- OpenConnection();
- DbTransaction trans = sqlConn.BeginTransaction();
- DbCommand cmd = CreateDbCommd(sqlConn, trans, sqlStr, cmdType, listParams);
- SqlDataAdapter sqlDataAdpter = new SqlDataAdapter(cmd as SqlCommand);
- DataTable dt = new DataTable();
- try
- {
- sqlDataAdpter.Fill(dt);
- trans.Commit();
- }
- catch (Exception e)
- {
- trans.Rollback();
- throw new Exception("执行数据库操作失败, sql: " + sqlStr, e);
- }
- finally
- {
- sqlDataAdpter.Dispose();
- cmd.Dispose();
- trans.Dispose();
- CloseConnection();
- }
- return dt;
- }
- public DataSet FillDataSet(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- OpenConnection();
- DbTransaction trans = sqlConn.BeginTransaction();
- DbCommand cmd = CreateDbCommd(sqlConn, trans, sqlStr, cmdType, listParams);
- SqlDataAdapter sqlDataAdpter = new SqlDataAdapter(cmd as SqlCommand);
- DataSet ds = new DataSet();
- try
- {
- sqlDataAdpter.Fill(ds);
- trans.Commit();
- }
- catch (Exception e)
- {
- trans.Rollback();
- throw new Exception("执行数据库操作失败, sql: " + sqlStr, e);
- }
- finally
- {
- sqlDataAdpter.Dispose();
- cmd.Dispose();
- trans.Dispose();
- CloseConnection();
- }
- return ds;
- }
- public object ExecuteScalar(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- object result = null;
- OpenConnection();
- DbTransaction trans = sqlConn.BeginTransaction();
- try
- {
- cmd = CreateDbCommd(sqlConn, trans, sqlStr, cmdType, listParams);
- result = cmd.ExecuteScalar();
- trans.Commit();
- }
- catch (Exception e)
- {
- trans.Rollback();
- throw new Exception("执行数据库操作失败, sql: " + sqlStr, e);
- }
- finally
- {
- trans.Dispose();
- CloseConnection();
- }
- return result;
- }
- public int ExecuteNonQuery(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- int result = -1;
- OpenConnection();
- DbTransaction trans = sqlConn.BeginTransaction();
- try
- {
- cmd = CreateDbCommd(sqlConn, trans, sqlStr, cmdType, listParams);
- result = cmd.ExecuteNonQuery();
- trans.Commit();
- }
- catch (Exception e)
- {
- trans.Rollback();
- throw new Exception("执行数据库操作失败, sql: " + sqlStr, e);
- }
- finally
- {
- trans.Dispose();
- CloseConnection();
- }
- return result;
- }
- /// <summary>
- /// 批量插入
- /// </summary>
- /// <param name="tableName"></param>
- /// <param name="batchSize"></param>
- /// <param name="copyTimeout"></param>
- /// <param name="dt"></param>
- /// <returns></returns>
- public bool ExecuteBatchInsert(string tableName, int batchSize, int copyTimeout, DataTable dt)
- {
- bool flag = false;
- try
- {
- using (TransactionScope scope = new TransactionScope())
- {
- OpenConnection();
- using (SqlBulkCopy sbc = new SqlBulkCopy(sqlConn as SqlConnection))
- {
- //服务器上目标表的名称
- sbc.DestinationTableName = tableName;
- sbc.BatchSize = batchSize;
- sbc.BulkCopyTimeout = copyTimeout;
- for (int i = 0; i < dt.Columns.Count; i++)
- {
- //列映射定义数据源中的列和目标表中的列之间的关系
- sbc.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
- }
- sbc.WriteToServer(dt);
- flag = true;
- scope.Complete();//有效的事务
- }
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- return flag;
- }
- public void OpenConnection()
- {
- if (sqlConn.State == ConnectionState.Broken || sqlConn.State == ConnectionState.Closed)
- sqlConn.Open();
- }
- public void CloseConnection()
- {
- sqlConn.Close();
- }
- #endregion
- #region dispose method
- /// <summary>
- /// dispose接口方法
- /// </summary>
- public void Dispose()
- {
- }
- #endregion
- }
- }
到这里,我们实现了SqlServer类里的方法,对Ms SqlServer数据库我们就已经可以进行简单的基础的CRUD操作了。
三、简单直观的对象实体转换
在第二步中,我们已经实现了简单的数据CRUD操作。根据楼猪使用ORM的经验和习惯,我们也应该对一些查询结果进行转换,因为以类的组织方式比直接呈现ADO.NET对象更容易让人接受,效率高低反在其次。下面利用常见的反射原理,简单实现一个对象实体转换器ModelConverter类:
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- using System.Reflection;
- using System.Threading;
- namespace AdoNetDataAccess.Core.Obj2Model
- {
- using AdoNetDataAccess.Core.Contract;
- public sealed class ModelConverter
- {
- private static readonly object objSync = new object();
- #region query for list
- /// <summary>
- /// 查询数据表项并转换为对应实体
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="objType"></param>
- /// <param name="rdr"></param>
- /// <returns></returns>
- public static IList<T> QueryForList<T>(string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType, IDbOperation dbOperation)
- where T : class, new()
- {
- IDataReader rdr = dbOperation.ExecuteReader(sqlStr, cmdType, listParams);
- IList<T> listModels = new List<T>();
- try
- {
- Monitor.Enter(objSync);
- Hashtable ht = CreateHashColumnName(rdr);
- while (rdr.Read())
- {
- Object obj = Activator.CreateInstance(objType);
- PropertyInfo[] properties = objType.GetProperties();
- foreach (PropertyInfo propInfo in properties)
- {
- string columnName = propInfo.Name.ToUpper();
- if (ht.ContainsKey(columnName) == false)
- {
- continue;
- }
- int index = rdr.GetOrdinal(propInfo.Name);
- object columnValue = rdr.GetValue(index);
- if (columnValue != System.DBNull.Value)
- {
- SetValue(propInfo, obj, columnValue);
- }
- }
- T model = default(T);
- model = obj as T;
- listModels.Add(model);
- }
- }
- finally
- {
- rdr.Close();
- rdr.Dispose();
- Monitor.Exit(objSync);
- }
- return listModels;
- }
- #endregion
- #region query for dictionary
- /// <summary>
- /// 查询数据表项并转换为对应实体
- /// </summary>
- /// <typeparam name="K"></typeparam>
- /// <typeparam name="T"></typeparam>
- /// <param name="key">字典对应key列名</param>
- /// <param name="objType"></param>
- /// <param name="rdr"></param>
- /// <returns></returns>
- public static IDictionary<K, T> QueryForDictionary<K, T>
- (string key, string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType, IDbOperation dbOperation)
- where T : class, new()
- {
- IDataReader rdr = dbOperation.ExecuteReader(sqlStr, cmdType, listParams);
- IDictionary<K, T> dictModels = new Dictionary<K, T>();
- try
- {
- Monitor.Enter(objSync);
- Hashtable ht = CreateHashColumnName(rdr);
- while (rdr.Read())
- {
- Object obj = Activator.CreateInstance(objType);
- PropertyInfo[] properties = objType.GetProperties();
- object dictKey = null;
- foreach (PropertyInfo propInfo in properties)
- {
- string columnName = propInfo.Name.ToUpper();
- if (ht.ContainsKey(columnName) == false)
- {
- continue;
- }
- int index = rdr.GetOrdinal(propInfo.Name);
- object columnValue = rdr.GetValue(index);
- if (columnValue != System.DBNull.Value)
- {
- SetValue(propInfo, obj, columnValue);
- if (string.Compare(columnName, key.ToUpper()) == 0)
- {
- dictKey = columnValue;
- }
- }
- }
- T model = default(T);
- model = obj as T;
- K objKey = (K)dictKey;
- dictModels.Add(objKey, model);
- }
- }
- finally
- {
- rdr.Close();
- rdr.Dispose();
- Monitor.Exit(objSync);
- }
- return dictModels;
- }
- #endregion
- #region internal util
- private static Hashtable CreateHashColumnName(IDataReader rdr)
- {
- int len = rdr.FieldCount;
- Hashtable ht = new Hashtable(len);
- for (int i = 0; i < len; i++)
- {
- string columnName = rdr.GetName(i).ToUpper(); //不区分大小写
- string columnRealName = rdr.GetName(i);
- if (ht.ContainsKey(columnName) == false)
- {
- ht.Add(columnName, columnRealName);
- }
- }
- return ht;
- }
- private static void SetValue(PropertyInfo propInfo, Object obj, object objValue)
- {
- try
- {
- propInfo.SetValue(obj, objValue, null);
- }
- catch
- {
- object realValue = null;
- try
- {
- realValue = Convert.ChangeType(objValue, propInfo.PropertyType);
- propInfo.SetValue(obj, realValue, null);
- }
- catch (Exception ex)
- {
- string err = ex.Message;
- //throw ex; //在数据库数据有不符合规范的情况下应该及时抛出异常
- }
- }
- }
- #endregion
- }
- }
到这里,简单的数据访问持久化层就实现了。下面模仿楼猪使用的IBatis.net,写个伪SqlMapper,改善一下调用形式,丰富一下调用方法,让方法辨识度更高。
四、实现伪SqlMapper
1、BaseMapper类
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- using System.Data.SqlClient;
- namespace AdoNetDataAccess.Mapper
- {
- using AdoNetDataAccess.Core.Contract;
- public abstract class BaseMapper
- {
- public IDbOperation CurrentDbOperation;
- #region query for list
- public abstract IList<T> QueryForList<T>(string sqlStr)
- where T : class, new();
- public abstract IList<T> QueryForList<T>(string sqlStr, Type objType)
- where T : class, new(); public abstract IList<T> QueryForList<T>(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- where T : class, new();
- public abstract IList<T> QueryForList<T>
- (string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType)
- where T : class, new();
- #endregion
- #region query for dictionary
- public abstract IDictionary<K, T> QueryForDictionary<K, T>(string key, string sqlStr)
- where T : class, new();
- public abstract IDictionary<K, T> QueryForDictionary<K, T>(string key, string sqlStr, Type objType)
- where T : class, new();
- public abstract IDictionary<K, T> QueryForDictionary<K, T>
- (string key, string sqlStr, CommandType cmdType, Type objType)
- where T : class, new();
- public abstract IDictionary<K, T> QueryForDictionary<K, T>
- (string key, string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType)
- where T : class, new();
- #endregion
- #region dataset datatable
- public abstract DataTable FillDataTable(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- public abstract DataSet FillDataSet(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- #endregion
- #region ExecuteScalar
- public abstract object ExecuteScalar(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- #endregion
- #region insert
- public abstract int Insert(string sqlStr);
- public abstract int Insert(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- public abstract bool BatchInsert(string tableName, int batchSize, int copyTimeout, DataTable dt);
- #endregion
- #region delete
- public abstract int Delete(string sqlStr);
- public abstract int Delete(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- #endregion
- #region update
- public abstract int Update(string sqlStr);
- public abstract int Update(string sqlStr, CommandType cmdType, List<DbParameter> listParams);
- #endregion
- }
- }
上面代码中的方法您是不是很熟悉呢? 呵呵,使用IBatis.net 的童鞋应该会和楼猪产生更多的共鸣。
2、SqlMapper类
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.Common;
- namespace AdoNetDataAccess.Mapper
- {
- using AdoNetDataAccess.Core.Contract;
- using AdoNetDataAccess.Core.Obj2Model;
- public class SqlMapper : BaseMapper
- {
- private SqlMapper()
- { }
- public SqlMapper(IDbOperation dbOperation)
- {
- this.CurrentDbOperation = dbOperation;
- }
- #region query for list
- public override IList<T> QueryForList<T>(string sqlStr)
- {
- return QueryForList<T>(sqlStr, CommandType.Text, null, typeof(T));
- }
- public override IList<T> QueryForList<T>(string sqlStr, Type objType)
- {
- return QueryForList<T>(sqlStr, CommandType.Text, null, objType);
- }
- public override IList<T> QueryForList<T>(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return QueryForList<T>(sqlStr, cmdType, listParams, typeof(T));
- }
- public override IList<T> QueryForList<T>(string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType)
- {
- return ModelConverter.QueryForList<T>(sqlStr, cmdType, listParams, objType, this.CurrentDbOperation);
- }
- #endregion
- #region query for dictionary
- public override IDictionary<K, T> QueryForDictionary<K, T>(string key, string sqlStr)
- {
- return QueryForDictionary<K, T>(key, sqlStr, CommandType.Text, null, typeof(T));
- }
- public override IDictionary<K, T> QueryForDictionary<K, T>(string key, string sqlStr, Type objType)
- {
- return QueryForDictionary<K, T>(key, sqlStr, CommandType.Text, null, objType);
- }
- public override IDictionary<K, T> QueryForDictionary<K, T>(string key, string sqlStr, CommandType cmdType, Type objType)
- {
- return QueryForDictionary<K, T>(key, sqlStr, cmdType, null, objType);
- }
- public override IDictionary<K, T> QueryForDictionary<K, T>
- (string key, string sqlStr, CommandType cmdType, List<DbParameter> listParams, Type objType)
- {
- return ModelConverter.QueryForDictionary<K, T>(key, sqlStr, cmdType, listParams, objType, this.CurrentDbOperation);
- }
- #endregion
- #region dataset datatable
- public override DataTable FillDataTable(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return this.CurrentDbOperation.FillDataTable(sqlStr, cmdType, listParams);
- }
- public override DataSet FillDataSet(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return this.CurrentDbOperation.FillDataSet(sqlStr, cmdType, listParams);
- }
- #endregion
- #region ExecuteScalar
- public override object ExecuteScalar(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return this.CurrentDbOperation.ExecuteScalar(sqlStr, cmdType, listParams);
- }
- #endregion
- #region insert
- public override int Insert(string sqlStr)
- {
- object obj = ExecuteScalar(sqlStr, CommandType.Text, null);
- int id = obj == null ? 0 : int.Parse(obj.ToString());
- return id;
- }
- public override int Insert(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- object obj = ExecuteScalar(sqlStr, cmdType, listParams);
- int id = obj == null ? 0 : int.Parse(obj.ToString());
- return id;
- }
- /// <summary>
- /// 批量插入
- /// </summary>
- /// <param name="tableName"></param>
- /// <param name="batchSize"></param>
- /// <param name="copyTimeout"></param>
- /// <param name="dt"></param>
- /// <returns></returns>
- public override bool BatchInsert(string tableName, int batchSize, int copyTimeout, DataTable dt)
- {
- return this.CurrentDbOperation.ExecuteBatchInsert(tableName, batchSize, copyTimeout, dt);
- }
- #endregion
- #region delete
- public override int Delete(string sqlStr)
- {
- return CommitSql(sqlStr, CommandType.Text, null);
- }
- public override int Delete(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return CommitSql(sqlStr, cmdType, listParams);
- }
- #endregion
- #region update
- public override int Update(string sqlStr)
- {
- return CommitSql(sqlStr, CommandType.Text, null);
- }
- public override int Update(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return CommitSql(sqlStr, cmdType, listParams);
- }
- #endregion
- #region commit and execute sql
- private int CommitSql(string sqlStr, CommandType cmdType, List<DbParameter> listParams)
- {
- return this.CurrentDbOperation.ExecuteNonQuery(sqlStr, cmdType, listParams);
- }
- #endregion
- #region dbparameter
- public DbParameter CreateParameter(string paraName, object paramValue)
- {
- return this.CurrentDbOperation.CreateDbPrameter(paraName, paramValue);
- }
- public List<DbParameter> CreateParameterList(string[] paraNames, object[] paramValues)
- {
- List<DbParameter> listParams = new List<DbParameter>();
- try
- {
- if (paraNames.Length != paramValues.Length)
- {
- throw new Exception("Param name and value is not equal.");
- }
- for (int i = 0; i < paraNames.Length; i++)
- {
- DbParameter param = CreateParameter(paraNames[i], paramValues[i]);
- listParams.Add(param);
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- return listParams;
- }
- #endregion
- }
- }
上面的方法丰富实现了CRUD的常见操作,其实主要还是调用了IDbOperation接口和方法。
五、dal层数据访问实现
在这里我们使用前一篇文章里实现的数据持久化层和伪SqlMapper对象,实现数据操作。下面我们来看看Dal下核心的Dao如何实现:
还记得我们在IBatis.net下面的dao类是怎么实现的吗?没错,我们根据一个基类BaseDAO和它的构造函数,实现dao的配置加载。但是楼猪的实现没有那么复杂和强大,本文的实现其实就是通过BaseDAO和构造函数获取数据库连接对象的key,初始化一个SqlMapper,然后利用SqlMapper对象进行基本的CRUD等等数据操作。那么我们如何利用BaseDAO和构造函数就像以前在IBatis.net系列文章里的提到的Dal层下那样进行SqlMapper的初始化呢?
1、在AdoNetDataAccess.Mapper下我们定义公共的BaseDAO类
- namespace AdoNetDataAccess.Mapper
- {
- public abstract class BaseDAO
- {
- #region Properties
- public SqlMapper SqlMapper { get; set; }
- #endregion
- #region Constructor
- private BaseDAO()
- {
- }
- /// <summary>
- /// SqlMapper属性适用
- /// </summary>
- /// <param name="mapperName"></param>
- public BaseDAO(string mapperName)
- {
- this.SqlMapper = MapperUtill.GetMapper(mapperName);
- }
- #endregion
- }
- }
2、初始化SqlMapper的实用类
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- namespace AdoNetDataAccess.Mapper
- {
- using AdoNetDataAccess.Core.Contract;
- using AdoNetDataAccess.Core.Implement;
- public sealed class MapperUtill
- {
- #region fields
- public static string currentSqlKey = "sqlConn";
- public static int cmdTimeOut = 15;
- private static readonly object objSync = new object();
- private static readonly IDictionary<string, SqlMapper> dictMappers = new Dictionary<string, SqlMapper>();
- #endregion
- #region constructor and methods
- private MapperUtill()
- {
- }
- static MapperUtill()
- {
- try
- {
- cmdTimeOut = int.Parse(ConfigurationManager.AppSettings["db_timeOut"]);
- }
- catch
- {
- cmdTimeOut = 15;
- }
- //实例化SqlDbMapper
- for (int i = 0; i < ConfigurationManager.ConnectionStrings.Count; i++)
- {
- string key = ConfigurationManager.ConnectionStrings[i].Name;
- string value = ConfigurationManager.ConnectionStrings[i].ConnectionString;
- CreateMapper(key, value, cmdTimeOut);
- }
- }
- public static SqlMapper GetSqlMapper(string key)
- {
- return MapperUtill.GetMapper(key);
- }
- public static SqlMapper GetCurrentSqlMapper()
- {
- return MapperUtill.GetMapper(currentSqlKey);
- }
- public static void CreateMapper(string connKey, string sqlConStr, int connTimeOut)
- {
- IDbOperation operation = new SqlServer(sqlConStr, connTimeOut);
- SqlMapper mapper = new SqlMapper(operation);
- dictMappers.Add(connKey.ToUpper().Trim(), mapper);//不区分大小写
- }
- public static SqlMapper GetMapper(string sqlConKey)
- {
- if (string.IsNullOrEmpty(sqlConKey))
- {
- throw new Exception("数据库连接字符串主键为空!");
- }
- sqlConKey = sqlConKey.ToUpper();//不区分大小写
- SqlMapper mapper = null;
- if (dictMappers.ContainsKey(sqlConKey))
- {
- mapper = dictMappers[sqlConKey];
- }
- else
- {
- throw new Exception(string.Format("没有{0}所对应的数据库连接", sqlConKey));
- }
- return mapper;
- }
- /// <summary>
- /// 释放所有
- /// </summary>
- public void Release()
- {
- foreach (KeyValuePair<string, SqlMapper> kv in dictMappers)
- {
- SqlMapper mapper = kv.Value;
- if (mapper == null)
- {
- continue;
- }
- mapper.CurrentDbOperation.CloseConnection();
- }
- dictMappers.Clear();
- }
- #endregion
- }
- }
这个实用类的重要作用就是初始化配置文件里connectionStrings配置节点,以获取sql连接对象必须的连接字符串。
3、PersonDao类
下面就是针对具体的Person表的数据操作了:
- using System.Collections.Generic;
- using System.Data;
- namespace AdoNetDataAccess.Dal.Dao
- {
- using AdoNetDataAccess.Dal.Model;
- using AdoNetDataAccess.Dal.Utility;
- using AdoNetDataAccess.Mapper;
- public class PersonDao : BaseDAO
- {
- public PersonDao()
- : base("sqlConn")//sqlConn是<connectionStrings>配置节点的一个name
- {
- }
- public int Insert(string sqlInsert)
- {
- int id = this.SqlMapper.Insert(sqlInsert);
- //object obj = this.SqlMapper.ExecuteScalar(sqlInsert, System.Data.CommandType.Text, null);
- return id;
- }
- public bool BatchInsert(IList<Person> listModels)
- {
- int batchSize = 50000;
- int copyTimeOut = 60;
- DataTable dt = DataTableHelper.CreateTable<Person>(listModels);
- bool flag = this.SqlMapper.BatchInsert(typeof(Person).Name, batchSize, copyTimeOut, dt);
- return flag;
- }
- public int Update(string sqlUpdate)
- {
- int result = this.SqlMapper.Update(sqlUpdate);
- return result;
- }
- public IList<Person> SelectPersons(string sqlSelect)
- {
- IList<Person> listPersons = this.SqlMapper.QueryForList<Person>(sqlSelect);
- return listPersons;
- }
- public IDictionary<int, Person> SelectDictPersons(string sqlSelect)
- {
- IDictionary<int, Person> dictPersons = this.SqlMapper.QueryForDictionary<int, Person>("Id", sqlSelect);
- return dictPersons;
- }
- public DataTable SelectPersonTable(string sqlSelect)
- {
- DataTable dt = this.SqlMapper.FillDataTable(sqlSelect, CommandType.Text, null);
- return dt;
- }
- public DataSet SelectPersonDataSet(string sqlSelect)
- {
- DataSet ds = this.SqlMapper.FillDataSet(sqlSelect, CommandType.Text, null);
- return ds;
- }
- public int Delete(string sqlDelete)
- {
- int result = this.SqlMapper.Delete(sqlDelete);
- return result;
- }
- }
- }
到这里,一个dao类操作就实现了。然后我们按步就班实现对外调用的服务接口。在表现层调用吧。
六、表现层的调用
1、配置文件
- <appSettings>
- <add key="db_timeOut" value="5000"/>
- </appSettings>
- <connectionStrings>
- <add name="sqlConn" connectionString="Data Source=.\sqlexpress; Initial Catalog=TestDb; User Id=sa; Password=123456;"/>
- <add name="sqlConnStr1" connectionString="Data Source=.\sqlexpress; Initial Catalog=TestDb; User Id=sa; Password=123456;"/>
- <add name="sqlConnStr2" connectionString="Data Source=.\sqlexpress; Initial Catalog=TestDb; User Id=sa; Password=123456;"/>
- </connectionStrings>
其中,connectionString是必须的,如果没有,我们无法加载调用可用的SqlMapper。
2、CRUD操作测试
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Data;
- namespace OOXXWebApp
- {
- using AdoNetDataAccess.Dal;
- using AdoNetDataAccess.Dal.Model;
- public partial class _Default : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!IsPostBack)
- {
- //增删改查测试
- string sqlInsert = "INSERT Person (FirstName,LastName,Weight,Height) VALUES( 'jeff','wong',70,180) SELECT @@IDENTITY FROM Person(NOLOCK)";
- string sqlUpdate = "UPDATE Person SET Height=178 WHERE Id=1";
- string sqlSelect = "SELECT TOP 100 * FROM Person(NOLOCK)";
- string sqlDelete = "DELETE Person WHERE Id>10 AND Id<100";
- IList<Person> listModels = new List<Person>();
- for (int i = 0; i < 500000; i++)
- {
- Person model = new Person();
- model.FirstName = "Jeff";
- model.LastName = "Wong";
- model.Weight = 70;
- model.Height = 180;
- listModels.Add(model);
- }
- Response.Write("Test Beginning......<br/>");
- int id = ServiceFactory.CreatePersonService().Add(sqlInsert);
- Response.Write(string.Format("<br/>Insert and return id:{0}", id));
- bool flag = ServiceFactory.CreatePersonService().BatchInsert(listModels);
- Response.Write(string.Format("<br/> Batch Insert {0}", flag ? "succeed" : "failed"));
- IList<Person> listPersons = ServiceFactory.CreatePersonService().GetPersons(sqlSelect);
- Response.Write(string.Format("<br/>Select pesons and return persons:{0}", listPersons.Count));
- IDictionary<int, Person> dictPersons = ServiceFactory.CreatePersonService().GetDictPersons(sqlSelect);
- Response.Write(string.Format("<br/>Select pesons and return dictionary persons:{0}", dictPersons.Count));
- DataTable dt = ServiceFactory.CreatePersonService().GetPersonTable(sqlSelect);
- Response.Write(string.Format("<br/>Select pesons and return persons:{0}", dt.Rows.Count));
- DataSet ds = ServiceFactory.CreatePersonService().GetPersonDataSet(sqlSelect);
- Response.Write(string.Format("<br/>Select pesons and return persons:{0}", ds.Tables[0].Rows.Count));
- int affectNum = ServiceFactory.CreatePersonService().Modify(sqlUpdate);
- Response.Write(string.Format("<br/>Update and affect rows :{0}", affectNum));
- affectNum = 0;
- affectNum = ServiceFactory.CreatePersonService().Remove(sqlDelete);
- Response.Write(string.Format("<br/>Delete and affect rows :{0}", affectNum));
- Response.Write("<br/><br/>Test End.");
- }
- }
- }
- }
这个就不用多说了吧,表现层写SQL语句调用写好的服务就行了。比较不舒服的地方就是SQL语句不得不写在类里面,如果自动生成或者独立放在xml下实现可配置的形式那就更好了,当然sql语句不是我们讨论的重点,您有好的方法可以自己扩展实现更人性化的功能,减少书写SQLl语句的工作。
七、最后,对demo工程文件结构进行简单说明。 1、数据持久化层AdoNetDataAccess.Core 2、SqlMapper层AdoNetDataAccess.Mapper(引用AdoNetDataAccess.Core) 3、具体数据操作使用层AdoNetDataAccess.Dal(引用AdoNetDataAccess.Mapper) 4、表现层AdoNetDataAccessWebApp(引用AdoNetDataAccess.Dal) 可以看出,工程里的文件结构还是很清晰的,需要学习的童鞋不妨下载使用试试看吧
相关demo:http://files.cnblogs.com/wjfluisfigo/AdoNetDataAccessOrm.rar
原文标题:ado.net快速上手实践篇(二)
链接:http://www.cnblogs.com/wjfluisfigo/archive/2010/05/23/1742034.html
【编辑推荐】