采用什么样的数据访问形式是软件编码很重要的一个环节,良好的数据访问形式不仅能够提搞代码的执行效率,协作能力,更重要的是对未来程序维护,功能扩展起到至关重要的作用。当然良好的设计模式可以为我们提供很多的选择,但面对实际问题,公司规模小考虑成本,资金投入少,软件逻辑不算复杂,功能较少,部分客户需求只需要单个功能模块,类似小型管理系统,门户网站,crm等,这也为众多IT人事提供了兼职的好机会。借鉴类似程序,cpy下部分代码,小修小改下数据库字段新的软件就大功告成。这种现状在弊端同时也很多程序没有通过完整的测试,部分存在漏洞,维护性不高,导致客户日常投诉反工现象时有发生,弄不好还会引起不必要的麻烦,为此组件一个高效便捷的快速开发框架,集成我们日常生活中的经验是十分有必要的。
这里我就结合几个项目中用到的简单的数据访问层简单和大家共同的学习探讨。
1、常用数据访问我们一般采用的都有:微软自带DBHelper
2、Enterprises Library微软企业库(Microsoft.Practices.EnterpriseLibrary.Common,Microsoft.Practices.EnterpriseLibrary.Data,Microsoft.Practices.ObjectBuilder)
3、这里我和大家共同探讨结合微软DBHelper的自定义的加强版SqlDataProvider.cs
数据库访问抽象类DataProvider.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data.SqlClient; 6 using System.Configuration; 7 using System.Data; 8 using System.Reflection; 9 using System.Data.OleDb; 10 namespace DAL 11 { 12 ///<summary> 13 /// 数据库访问抽象类 14 ///</summary> 15 public abstract class DataProvider 16 { 17 private static DataProvider _instance = null; 18 public static DataProvider Instance 19 { 20 get 21 { 22 if (_instance == null) 23 { 24 String strConnectionString = ConfigurationManager.ConnectionStrings["ConnnectionString"].ConnectionString; 25 26 String strConnectionType = ConfigurationManager.ConnectionStrings["ConnectionType"].ConnectionString; 27 if (strConnectionType.ToLower() == "sqlclient") 28 { 29 strConnectionType = "DAL.SqlDataProvider, DAL"; 30 } 31 32 Type t = Type.GetType(strConnectionType); 33 Type[] paramTypes = new Type[1]; 34 paramTypes[0] = typeof(String); 35 36 Object[] paramArray = new Object[1]; 37 paramArray[0] = strConnectionString; 38 39 _instance = (DataProvider)((ConstructorInfo)t.GetConstructor(paramTypes)).Invoke(paramArray); 40 } 41 return _instance; 42 } 43 } 44 45 #region 抽象属性和方法 46 47 #region 数据库链接串 48 public abstract String ConnectionString { get; } 49 #endregion 50 51 #region 执行SQL语句 52 public abstract Object GetScalar(String selectSql); 53 public abstract DataSet GetDataset(String selectSql); 54 public virtual DataSet GetDatasetTrans(SqlTransaction trans, String selectSql) { return null; } 55 public virtual DataSet GetDatasetTrans(OleDbTransaction trans, String selectSql) { return null; } 56 public virtual DataSet GetDataset(String selectSql, SqlParameter[] para) { return null; } 57 public virtual DataSet GetDataset(String selectSql, OleDbParameter[] para) { return null; } 58 public virtual DataSet GetDatasetTrans(SqlTransaction trans, String selectSql, SqlParameter[] para) { return null; } 59 public virtual DataSet GetDatasetTrans(OleDbTransaction trans, String selectSql, OleDbParameter[] para) { return null; } 60 public abstract void Execute(String noneQuery); 61 public virtual void Execute(String noneQuery, SqlParameter[] para) { } 62 public virtual void Execute(String noneQuery, OleDbParameter[] para) { } 63 public abstract IDataReader GetReader(String selectSql); 64 public virtual IDataReader GetReaderTrans(SqlTransaction trans, String selectSql) { return null; } 65 public virtual IDataReader GetReaderTrans(OleDbTransaction trans, String selectSql) { return null; } 66 public virtual IDataReader GetReader(String selectSql, SqlParameter[] para) { return null; } 67 public virtual IDataReader GetReader(String selectSql, OleDbParameter[] para) { return null; } 68 public virtual IDataReader GetReaderTrans(SqlTransaction trans, String selectSql, SqlParameter[] para) { return null; } 69 public virtual IDataReader GetReaderTrans(OleDbTransaction trans, String selectSql, OleDbParameter[] para) { return null; } 70 #endregion 71 72 #region 执行存储过程 73 public abstract void ExecuteSp(String spName); 74 public virtual void ExecuteSp(SqlTransaction trans, String spName) { } 75 public virtual void ExecuteSp(OleDbTransaction trans, String spName) { } 76 public virtual void ExecuteSp(String spName, SqlParameter[] para) { } 77 public virtual void ExecuteSp(String spName, OleDbParameter[] para) { } 78 public virtual void ExecuteSp(SqlTransaction trans, String spName, SqlParameter[] para) { } 79 public virtual void ExecuteSp(OleDbTransaction trans, String spName, OleDbParameter[] para) { } 80 public abstract IDataReader GetReaderBySp(String spName); 81 public virtual IDataReader GetReaderBySp(String spName, SqlParameter[] para) { return null; } 82 public virtual IDataReader GetReaderBySp(String spName, OleDbParameter[] para) { return null; } 83 public abstract Object GetScalarBySp(String spName); 84 public virtual Object GetScalarBySp(String spName, SqlParameter[] para) { return null; } 85 public virtual Object GetScalarBySp(String spName, OleDbParameter[] para) { return null; } 86 public abstract DataSet GetDatasetBySp(String spName); 87 public virtual DataSet GetDatasetBySp(String spName, SqlParameter[] para) { return null; } 88 public virtual DataSet GetDatasetBySp(String spName, OleDbParameter[] para) { return null; } 89 #endregion 90 91 #endregion 92 } 93 }
继承类SqlDataProvider:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data; 6 using System.Data.SqlClient; 7 namespace DAL 8 { 9 public class SqlDataProvider : DataProvider 10 { 11 private String _connectionString = String.Empty; 12 13 public SqlDataProvider(String connString) 14 { 15 _connectionString = connString; 16 } 17 18 #region 实现抽象方法 19 20 #region 数据库链接串 21 public override String ConnectionString 22 { 23 get 24 { 25 return _connectionString; 26 } 27 } 28 29 #endregion 30 31 #region 执行SQL语句 32 33 ///<summary> 34 /// 执行查询获取单值 35 ///</summary> 36 ///<param name="selectSql">查询语句</param> 37 ///<returns>返回Object</returns> 38 public override Object GetScalar(String selectSql) 39 { 40 return SqlHelper.ExecuteScalar(_connectionString, 41 CommandType.Text, selectSql); 42 } 43 44 ///<summary> 45 /// 根据查询语句获取数据集 46 ///</summary> 47 ///<param name="selectSql">查询语句</param> 48 ///<returns>返回数据集</returns> 49 public override DataSet GetDataset(String selectSql) 50 { 51 if (selectSql == null) throw new ArgumentNullException("selectSql"); 52 53 DataSet ds = new DataSet(); 54 SqlHelper.FillDataset(_connectionString, CommandType.Text, selectSql, ds, null); 55 return ds; 56 } 57 58 ///<summary> 59 /// 根据查询语句获取数据集 60 ///</summary> 61 ///<param name="trans">事务</param> 62 ///<param name="selectSql">查询语句</param> 63 ///<returns>返回数据集</returns> 64 public override DataSet GetDatasetTrans(SqlTransaction trans, String selectSql) 65 { 66 if (selectSql == null) throw new ArgumentNullException("selectSql"); 67 68 DataSet ds = new DataSet(); 69 SqlHelper.FillDataset(trans, CommandType.Text, selectSql, ds, null); 70 return ds; 71 } 72 73 ///<summary> 74 /// 根据带参数的查询语句获取数据集 75 ///</summary> 76 ///<param name="selectSql">查询语句</param> 77 ///<param name="para">参数列表</param> 78 ///<returns>返回数据集</returns> 79 public override DataSet GetDataset(String selectSql, SqlParameter[] para) 80 { 81 if (selectSql == null) throw new ArgumentNullException("selectSql"); 82 if (para == null) throw new ArgumentNullException("para"); 83 84 DataSet ds = new DataSet(); 85 SqlHelper.FillDataset(_connectionString, CommandType.Text, selectSql, ds, null, para); 86 return ds; 87 } 88 89 ///<summary> 90 /// 根据带参数的查询语句获取数据集 91 ///</summary> 92 ///<param name="trans">事务</param> 93 ///<param name="selectSql">查询语句</param> 94 ///<param name="para">参数列表</param> 95 ///<returns>返回数据集</returns> 96 public override DataSet GetDatasetTrans(SqlTransaction trans, String selectSql, SqlParameter[] para) 97 { 98 if (selectSql == null) throw new ArgumentNullException("selectSql"); 99 if (para == null) throw new ArgumentNullException("para"); 100 101 DataSet ds = new DataSet(); 102 SqlHelper.FillDataset(trans, CommandType.Text, selectSql, ds, null, para); 103 return ds; 104 } 105 106 ///<summary> 107 /// 在某个数据库连接对象上执行查询语句获取数据集 108 ///</summary> 109 ///<param name="cn">数据库连接对象</param> 110 ///<param name="selectSql">查询语句</param> 111 ///<returns>返回数据集</returns> 112 public static DataSet GetDataset(SqlConnection conn, String selectSql) 113 { 114 if (conn == null) throw new ArgumentNullException("conn"); 115 if (selectSql == null) throw new ArgumentNullException("selectSql"); 116 117 DataSet ds = new DataSet(); 118 SqlHelper.FillDataset(conn, CommandType.Text, selectSql, ds, null); 119 return ds; 120 } 121 122 ///<summary> 123 /// 执行非查询语句 124 ///</summary> 125 ///<param name="noneQuery">非查询sql语句</param> 126 public override void Execute(String noneQuery) 127 { 128 if (noneQuery == null) throw new ArgumentNullException("noneQuery"); 129 130 SqlHelper.ExecuteNonQuery(_connectionString, CommandType.Text, noneQuery); 131 } 132 133 ///<summary> 134 /// 执行非查询语句 135 ///</summary> 136 ///<param name="noneQuery">非查询sql语句</param> 137 ///<param name="para">参数列表</param> 138 public override void Execute(String noneQuery, SqlParameter[] para) 139 { 140 if (noneQuery == null) throw new ArgumentNullException("noneQuery"); 141 if (para == null) throw new ArgumentNullException("para"); 142 143 SqlHelper.ExecuteNonQuery(_connectionString, CommandType.Text, noneQuery, para); 144 } 145 146 ///<summary> 147 /// 执行查询语句获取Reader对象 148 ///</summary> 149 ///<param name="selectSql">查询语句</param> 150 ///<returns>返回DataReader</returns> 151 public override IDataReader GetReader(String selectSql) 152 { 153 if (selectSql == null) throw new ArgumentNullException("selectSql"); 154 155 return SqlHelper.ExecuteReader(_connectionString, CommandType.Text, selectSql); 156 } 157 158 ///<summary> 159 /// 执行查询语句获取Reader对象 160 ///</summary> 161 ///<param name="trans">事务</param> 162 ///<param name="selectSql">查询语句</param> 163 ///<returns>返回DataReader</returns> 164 public override IDataReader GetReaderTrans(SqlTransaction trans, String selectSql) 165 { 166 if (selectSql == null) throw new ArgumentNullException("selectSql"); 167 168 return SqlHelper.ExecuteReader(trans, CommandType.Text, selectSql); 169 } 170 171 ///<summary> 172 /// 执行查询语句获取Reader对象 173 ///</summary> 174 ///<param name="selectSql">查询语句</param> 175 ///<param name="para">参数列表</param> 176 ///<returns>返回DataReader</returns> 177 public override IDataReader GetReader(String selectSql, SqlParameter[] para) 178 { 179 if (selectSql == null) throw new ArgumentNullException("selectSql"); 180 if (para == null) throw new ArgumentNullException("para"); 181 182 return SqlHelper.ExecuteReader(_connectionString, CommandType.Text, selectSql, para); 183 } 184 185 ///<summary> 186 /// 执行查询语句获取Reader对象 187 ///</summary> 188 ///<param name="trans">事务</param> 189 ///<param name="selectSql">查询语句</param> 190 ///<param name="para">参数列表</param> 191 ///<returns>返回DataReader</returns> 192 public override IDataReader GetReaderTrans(SqlTransaction trans, String selectSql, SqlParameter[] para) 193 { 194 if (selectSql == null) throw new ArgumentNullException("selectSql"); 195 if (para == null) throw new ArgumentNullException("para"); 196 197 return SqlHelper.ExecuteReader(trans, CommandType.Text, selectSql, para); 198 } 199 200 #endregion 201 202 #region 执行存储过程 203 ///<summary> 204 /// 执行非查询存储过程 205 ///</summary> 206 ///<param name="spName">存储过程名称</param> 207 public override void ExecuteSp(String spName) 208 { 209 if (spName == null) throw new ArgumentNullException("spName"); 210 211 SqlHelper.ExecuteNonQuery(_connectionString, CommandType.StoredProcedure, spName); 212 } 213 214 ///<summary> 215 /// 执行非查询存储过程 216 ///</summary> 217 ///<param name="trans">事务对象</param> 218 ///<param name="spName">存储过程名称</param> 219 public override void ExecuteSp(SqlTransaction trans, String spName) 220 { 221 if (trans == null) throw new ArgumentNullException("trans"); 222 if (spName == null) throw new ArgumentNullException("spName"); 223 224 SqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, spName); 225 } 226 227 ///<summary> 228 /// 执行非查询存储过程 229 ///</summary> 230 ///<param name="spName">存储过程名称</param> 231 ///<param name="para">参数列表</param> 232 public override void ExecuteSp(String spName, SqlParameter[] para) 233 { 234 if (spName == null) throw new ArgumentNullException("spName"); 235 if (para == null) throw new ArgumentNullException("para"); 236 237 SqlHelper.ExecuteNonQuery(_connectionString, CommandType.StoredProcedure, spName, para); 238 } 239 240 /// 执行非查询存储过程 241 ///</summary> 242 ///<param name="trans">事务对象</param> 243 ///<param name="spName">存储过程名称</param> 244 ///<param name="para">参数列表</param> 245 public override void ExecuteSp(SqlTransaction trans, String spName, SqlParameter[] para) 246 { 247 if (trans == null) throw new ArgumentNullException("trans"); 248 if (spName == null) throw new ArgumentNullException("spName"); 249 if (para == null) throw new ArgumentNullException("para"); 250 251 SqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, 252 spName, para); 253 } 254 255 ///<summary> 256 /// 执行查询存储过程获取Reader对象 257 ///</summary> 258 ///<param name="spName">存储过程名称</param> 259 ///<returns>返回DataReader</returns> 260 public override IDataReader GetReaderBySp(String spName) 261 { 262 if (spName == null) throw new ArgumentNullException("spName"); 263 264 return SqlHelper.ExecuteReader(_connectionString, 265 CommandType.StoredProcedure, spName); 266 } 267 268 ///<summary> 269 /// 执行查询存储过程获取Reader对象 270 ///</summary> 271 ///<param name="spName">存储过程名称</param> 272 ///<param name="para">参数列表</param> 273 ///<returns>返回DataReader</returns> 274 public override IDataReader GetReaderBySp(String spName, SqlParameter[] para) 275 { 276 return SqlHelper.ExecuteReader(_connectionString, 277 CommandType.StoredProcedure, spName, para); 278 } 279 280 ///<summary> 281 /// 执行查询存储过程获取单值 282 ///</summary> 283 ///<param name="spName">存储过程名称</param> 284 ///<returns>返回Object</returns> 285 public override Object GetScalarBySp(String spName) 286 { 287 return SqlHelper.ExecuteScalar(_connectionString, 288 CommandType.StoredProcedure, spName); 289 } 290 291 ///<summary> 292 /// 执行查询存储过程获取单值 293 ///</summary> 294 ///<param name="spName">存储过程名称</param> 295 ///<param name="para">参数列表</param> 296 ///<returns>返回Object</returns> 297 public override Object GetScalarBySp(String spName, SqlParameter[] para) 298 { 299 return SqlHelper.ExecuteScalar(_connectionString, 300 CommandType.StoredProcedure, spName, para); 301 } 302 303 ///<summary> 304 /// 根据存储过程获取数据集 305 ///</summary> 306 ///<param name="spName">存储过程</param> 307 ///<returns>返回数据集</returns> 308 public override DataSet GetDatasetBySp(String spName) 309 { 310 if (spName == null) throw new ArgumentNullException("spName"); 311 312 DataSet ds = new DataSet(); 313 SqlHelper.FillDataset(_connectionString, CommandType.StoredProcedure, spName, ds, null); 314 return ds; 315 } 316 ///<summary> 317 /// 根据带参数的存储过程获取数据集 318 ///</summary> 319 ///<param name="spName">存储过程</param> 320 ///<param name="para">参数列表</param> 321 ///<returns>返回数据集</returns> 322 public override DataSet GetDatasetBySp(String spName, SqlParameter[] para) 323 { 324 if (spName == null) throw new ArgumentNullException("spName"); 325 if (para == null) throw new ArgumentNullException("para"); 326 327 DataSet ds = new DataSet(); 328 SqlHelper.FillDataset(_connectionString, CommandType.StoredProcedure, spName, ds, null, para); 329 return ds; 330 } 331 #endregion 332 333 #endregion 334 } 335 }
微软本身是的SqlHelper类提供高性能可扩充的数据库访问方法,代码就不啰嗦大家都懂的,通过集成和改造对数据访问的安全性,扩展性做进一步的伸展
测试 同时加载1w条数据试一试,方法执行时间,忽略浏览器加载时间
改造数据访问:
方法执行时间
企业库:
方法执行时间
普通DBHlper:
方法执行时间
同时加载10W条数据试一试:
改造后10W条数据访问时间:
企业库10W数据访问时间:
普通DBHelper,10W条数据访问时间:
当然了测试和机器配置也相关,以上数据仅供参考,不一定准确,还有很多地方不是很完善,你的项目采用的是什么数据交互模式来?有没有更好的意见和建议,期待达人们的意见和建议。