虽然现在有层出不穷的各种ORM框架来与数据库交互,但是其底层也无外乎调用ADO.NET来处理,所以ADO.NET是根本,而且对于传统的老三层项目,大家想都不用想就能说出数据库操作有各种完善的SqlHelper。
别人的自己用了总是有不爽的地方,所以花时间把现有的SqlHelper全部改写了一下,充分利用泛型的以及委托的特性。
先来个代码截图
主要代码如下:
1.批量SQL语句处理类创建
1 ///2 /// 批量SQL定义 3 /// 4 public sealed class BatchCmdEntity 5 { 6 //参数列表 7 private readonly List _mParas; 8 9 public BatchCmdEntity() 10 { 11 _mParas = new List (); 12 } 13 14 /// 15 /// SQL语句 16 /// 17 public string Sql { get; set; } 18 19 /// 20 /// 参数数组属性 21 /// 22 public SqlParameter[] Parameter => _mParas.ToArray(); 23 24 /// 25 /// 添加参数 26 /// 27 /// 参数名称 28 /// 参数值 29 public void AddParameter(string name, object value) 30 { 31 _mParas.Add(new SqlParameter(name, value)); 32 } 33 34 /// 35 /// 添加参数数组 36 /// 37 /// 参数数组 38 public void AddParameter(SqlParameter[] paras) 39 { 40 _mParas.AddRange(paras); 41 } 42 }
有些场景比如ExecuteNonQuery需要返回多条语句叠加的数量结果是可以采用此类来封装
2.处理数据库空值方法
1 #region 【处理数据库空值方法】 2 3 ///4 /// 处理数据库空值方法 5 /// 6 /// 泛型类型 7 /// 读取出来的值 8 /// 泛型类型的默认值 9 /// 10 private static T ConvertData (object value, T defaultValue) 11 { 12 if (Convert.IsDBNull(value) || value == null) 13 { 14 return defaultValue; 15 } 16 if (value is T) 17 { 18 return (T)value; 19 } 20 return (T)Convert.ChangeType(value, typeof(T)); 21 } 22 23 #endregion
有些场景比如ExecuteScalar需要返回首行首列的值,该值可能为空,如果不为空则为object类型,需要返回我们需要的类型如int,string,double等,可以调用此方法
3.生成分页SQL语句,采用row_number函数
1 #region【BuildPagingSql】 2 3 ///4 /// 生成分页语句 5 /// 6 /// 分页字段 7 /// 查询SQL语句 8 /// 每页数量 9 /// 页索引 10 /// 11 public static string BuildPagingSql(string orderByField, string querySql, int pageSize, int pageIndex) 12 { 13 //开始记录数 14 int beginRowNum = (pageIndex - 1) * pageSize + 1; 15 //结束记录数 16 int endRowNum = pageIndex * pageSize; 17 18 StringBuilder sb = new StringBuilder(); 19 sb.Append(@"SELECT * "); 20 sb.AppendFormat($" FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY {orderByField} ) ROWNUMBER, *"); 21 sb.AppendFormat($" FROM ({querySql}) a) b "); 22 sb.AppendFormat($" WHERE ROWNUMBER BETWEEN {beginRowNum} AND {endRowNum}"); 23 24 return sb.ToString(); 25 }
现在的系统基本都不大使用存储过程,存储过程的弊端大家都知道,不好迁移,不利于做分库,所以采用row_number函数生成SQL语句来处理分页
4.其他代码大家应该理解起来没多大难度,完整代码如下,如有错误,欢迎告知,感谢
1 #region 2 3 using System; 4 using System.Collections.Generic; 5 using System.Configuration; 6 using System.Data; 7 using System.Data.SqlClient; 8 using System.Linq; 9 using System.Text; 10 11 #endregion 12 13 namespace OAO2O.BusinessService.DAL 14 { 15 ///16 /// DbHelper 的摘要说明 17 /// 18 public sealed class SqlHelper 19 { 20 //连接字符串从配置文件中读取 21 public static readonly string ConnString = ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString; 22 23 #region【ExecuteNonQuery】 24 25 /// 26 /// 生成使用默认连接的ExecuteNonQuery 27 /// 28 /// 语句 29 /// 类型 30 /// 参数数组 31 /// 32 public static int ExecuteNonQuery(string commandText, CommandType cmdType, params SqlParameter[] paras) 33 { 34 return ExecuteNonQuery(ConnString, commandText, cmdType, paras); 35 } 36 37 /// 38 /// 生成使用自定义连接的ExecuteNonQuery 39 /// 40 /// 自定义连接字符串 41 /// 语句 42 /// 类型 43 /// 参数数组 44 /// 45 public static int ExecuteNonQuery(string connectionString, string commandText, CommandType cmdType, 46 params SqlParameter[] parms) 47 { 48 using (SqlConnection connection = new SqlConnection(connectionString)) 49 { 50 using (SqlCommand command = new SqlCommand()) 51 { 52 PrepareCommand(command, connection, null, cmdType, commandText, parms); 53 int retval = command.ExecuteNonQuery(); 54 command.Parameters.Clear(); 55 return retval; 56 } 57 } 58 } 59 60 /// 61 /// 生成使用默认连接的ExecuteNonQuery 62 /// 63 /// 批量SQL语句 64 /// 65 public static int ExecuteNonQuery(List cmdList) 66 { 67 return ExecuteNonQuery(ConnString, cmdList); 68 } 69 70 /// 71 /// 生成使用自定义连接的ExecuteNonQuery 72 /// 73 /// 自定义连接字符串 74 /// 批量SQL语句 75 /// 76 public static int ExecuteNonQuery(string connectionString, List cmdList) 77 { 78 return ExecuteNonQuery(connectionString, command => 79 { 80 int retval = 0; 81 foreach (BatchCmdEntity cmd in cmdList) 82 { 83 //因为是批量语句,所以进来之前先清空 84 command.CommandText = ""; 85 command.Parameters.Clear(); 86 //重新赋值 87 command.CommandText = cmd.Sql; 88 command.Parameters.AddRange(cmd.Parameter); 89 retval += command.ExecuteNonQuery(); 90 } 91 92 return retval; 93 }); 94 } 95 96 /// 97 /// 生成使用默认连接的ExecuteNonQuery 98 /// 99 /// 泛型委托方法 100 /// 101 public static int ExecuteNonQuery(Func int> fun) 102 { 103 return ExecuteNonQuery(ConnString, fun); 104 } 105 106 /// 107 /// 生成使用自定义连接的ExecuteNonQuery 108 /// 109 /// 自定义连接字符串 110 /// 泛型委托方法 111 /// 112 public static int ExecuteNonQuery(string connectionString, Func int> fun) 113 { 114 using (SqlConnection connection = new SqlConnection(connectionString)) 115 { 116 if (connection.State != ConnectionState.Open) connection.Open(); 117 118 SqlTransaction trans = connection.BeginTransaction(); 119 using (SqlCommand command = new SqlCommand()) 120 { 121 PrepareCommand(command, connection, trans); 122 int retval = 0; 123 try 124 { 125 retval = fun(command); 126 trans.Commit(); 127 } 128 catch 129 { 130 trans.Rollback(); 131 132 } 133 return retval; 134 } 135 } 136 } 137 138 #endregion 139 140 #region 【ExecuteScalar】 141 142 /// 143 /// 生成使用默认连接的ExecuteScalar 144 /// 145 /// 泛型类型 146 /// 语句 147 /// 类型 148 /// 参数数组 149 /// 150 public static T ExecuteScalar (string commandText, CommandType cmdType, params SqlParameter[] parms) 151 { 152 return ExecuteScalar (ConnString, commandText, cmdType, parms); 153 } 154 155 /// 156 /// 生成使用自定义连接的ExecuteScalar 157 /// 158 /// 泛型类型 159 /// 自定义连接字符串 160 /// 语句 161 /// 类型 162 /// 参数数组 163 /// 164 public static T ExecuteScalar (string connectionString, string commandText, CommandType cmdType, 165 params SqlParameter[] parms) 166 { 167 using (SqlConnection connection = new SqlConnection(connectionString)) 168 { 169 using (SqlCommand command = new SqlCommand()) 170 { 171 PrepareCommand(command, connection, null, cmdType, commandText, parms); 172 object retval = command.ExecuteScalar(); 173 command.Parameters.Clear(); 174 return ConvertData(retval, default(T)); 175 } 176 } 177 } 178 179 #endregion 180 181 #region 【ExecuteDataRow】 182 183 public static DataRow ExecuteDataRow(string commandText, CommandType cmdType, params SqlParameter[] parms) 184 { 185 return ExecuteDataRow(ConnString, commandText, cmdType, parms); 186 } 187 188 /// 189 /// 生成数据行DataRow 190 /// 191 /// 192 /// 193 /// 194 /// 195 /// 196 public static DataRow ExecuteDataRow(string connectionString, string commandText, CommandType cmdType, 197 params SqlParameter[] parms) 198 { 199 DataTable data = ExecuteDataTable(connectionString, commandText, cmdType, parms); 200 return data?.Rows[0]; 201 } 202 203 #endregion 204 205 #region 【ExecuteDataTable】 206 207 public static DataTable ExecuteDataTable(string commandText, CommandType cmdType, params SqlParameter[] paras) 208 { 209 return ExecuteDataTable(ConnString, commandText, cmdType, paras); 210 } 211 212 /// 213 /// 生成数据表DataTable 214 /// 215 /// 连接字符串 216 /// 语句 217 /// 类型 218 /// 参数数组 219 /// 220 public static DataTable ExecuteDataTable(string connectionString, string commandText, CommandType cmdType, 221 params SqlParameter[] parms) 222 { 223 using (SqlConnection connection = new SqlConnection(connectionString)) 224 { 225 using (SqlCommand command = new SqlCommand()) 226 { 227 PrepareCommand(command, connection, null, cmdType, commandText, parms); 228 SqlDataAdapter adapter = new SqlDataAdapter(command); 229 230 DataTable data = new DataTable(); 231 adapter.Fill(data); 232 command.Parameters.Clear(); 233 234 return data; 235 } 236 } 237 } 238 239 #endregion 240 241 #region【ExecuteDataSet】 242 243 public static DataSet ExecuteDataSet(string cmdText, CommandType cmdType, params SqlParameter[] parms) 244 { 245 return ExecuteDataSet(ConnString, cmdText, cmdType, parms); 246 } 247 248 /// 249 /// 生成数据集合DataSet 250 /// 251 /// 连接字符串 252 /// 语句 253 /// 类型 254 /// 参数数组 255 /// 256 public static DataSet ExecuteDataSet(string connectionString, string commandText, CommandType cmdType, 257 params SqlParameter[] parms) 258 { 259 using (SqlConnection connection = new SqlConnection(connectionString)) 260 { 261 using (SqlCommand command = new SqlCommand()) 262 { 263 PrepareCommand(command, connection, null, cmdType, commandText, parms); 264 SqlDataAdapter adapter = new SqlDataAdapter(command); 265 266 DataSet data = new DataSet(); 267 adapter.Fill(data); 268 command.Parameters.Clear(); 269 270 return data; 271 } 272 } 273 } 274 275 #endregion 276 277 #region 【PrepareCommand】 278 279 private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction) 280 { 281 PrepareCommand(command, connection, transaction, CommandType.Text, string.Empty, null); 282 } 283 284 /// 285 /// 生成cmd 286 /// 287 /// cmd对象 288 /// 连接 289 /// 事务 290 /// 类型 291 /// 语句 292 /// 参数数组 293 private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, 294 CommandType commandType, string commandText, params SqlParameter[] parms) 295 { 296 if (connection.State != ConnectionState.Open) connection.Open(); 297 298 command.Connection = connection; 299 command.CommandTimeout = 600; 300 command.CommandText = commandText; 301 command.CommandType = commandType; 302 303 if (transaction != null) command.Transaction = transaction; 304 305 if (parms == null || parms.Length == 0) return; 306 //循环设置参数值为null的参数,设置其值为数据库制定类型DBNull.Value 307 foreach (SqlParameter parameter in parms.Where(parameter => (parameter.Direction == ParameterDirection.InputOutput || 308 parameter.Direction == ParameterDirection.Input) && 309 (parameter.Value == null))) 310 { 311 parameter.Value = DBNull.Value; 312 } 313 //添加到参数数组中 314 command.Parameters.AddRange(parms); 315 } 316 317 #endregion 318 319 #region 【BuildPara】 320 /// 321 /// 生成普通参数 322 /// 323 /// 参数名 324 /// 参数值 325 /// 326 public static SqlParameter BuildPara(string name, object value) 327 { 328 return new SqlParameter(name, value); 329 } 330 331 /// 332 /// 生成普通参数 333 /// 334 /// 参数名 335 /// 参数类型 336 /// 参数值 337 /// 338 public static SqlParameter BuildPara(string name, SqlDbType dbType, object value) 339 { 340 return new SqlParameter(name, dbType) 341 { 342 Value = value 343 }; 344 } 345 346 /// 347 /// 生成输出参数 348 /// 349 /// 参数名 350 /// 输出方向 351 /// 参数值 352 /// 353 public static SqlParameter BuildPara(string name, ParameterDirection direction, object value) 354 { 355 return new SqlParameter 356 { 357 ParameterName = name, 358 Direction = direction, 359 Value = value 360 }; 361 } 362 363 /// 364 /// 生成输出参数 365 /// 366 /// 参数名 367 /// 参数类型 368 /// 输出方向 369 /// 370 public static SqlParameter BuildPara(string name, SqlDbType dbType, ParameterDirection direction) 371 { 372 return new SqlParameter(name, dbType) 373 { 374 Direction = direction 375 }; 376 } 377 378 /// 379 /// 生成带长度的输出参数 380 /// 381 /// 参数名 382 /// 参数类型 383 /// 长度 384 /// 输出方向 385 /// 386 public static SqlParameter BuildPara(string name, SqlDbType dbType, int size, ParameterDirection direction) 387 { 388 return new SqlParameter(name, dbType, size) 389 { 390 Direction = direction 391 }; 392 } 393 394 /// 395 /// 生成输出参数 396 /// 397 /// 参数名 398 /// 参数类型 399 /// 输出方向 400 /// 参数值 401 /// 402 public static SqlParameter BuildPara(string name, SqlDbType dbType, ParameterDirection direction, object value) 403 { 404 return new SqlParameter(name, dbType) 405 { 406 Direction = direction, 407 Value = value 408 }; 409 } 410 411 #endregion 412 413 #region【BuildPagingSql】 414 415 /// 416 /// 生成分页语句 417 /// 418 /// 分页字段 419 /// 查询SQL语句 420 /// 每页数量 421 /// 页索引 422 /// 423 public static string BuildPagingSql(string orderByField, string querySql, int pageSize, int pageIndex) 424 { 425 //开始记录数 426 int beginRowNum = (pageIndex - 1) * pageSize + 1; 427 //结束记录数 428 int endRowNum = pageIndex * pageSize; 429 430 StringBuilder sb = new StringBuilder(); 431 sb.Append(@"SELECT * "); 432 sb.AppendFormat($" FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY {orderByField} ) ROWNUMBER, *"); 433 sb.AppendFormat($" FROM ({querySql}) a) b "); 434 sb.AppendFormat($" WHERE ROWNUMBER BETWEEN {beginRowNum} AND {endRowNum}"); 435 436 return sb.ToString(); 437 } 438 439 #endregion 440 441 #region 【处理数据库空值方法】 442 443 /// 444 /// 处理数据库空值方法 445 /// 446 /// 泛型类型 447 /// 读取出来的值 448 /// 泛型类型的默认值 449 /// 450 private static T ConvertData (object value, T defaultValue) 451 { 452 if (Convert.IsDBNull(value) || value == null) 453 { 454 return defaultValue; 455 } 456 if (value is T) 457 { 458 return (T)value; 459 } 460 return (T)Convert.ChangeType(value, typeof(T)); 461 } 462 463 #endregion 464 } 465 466 467 /// 468 /// 批量SQL定义 469 /// 470 public sealed class BatchCmdEntity 471 { 472 //参数列表 473 private readonly List _mParas; 474 475 public BatchCmdEntity() 476 { 477 _mParas = new List (); 478 } 479 480 /// 481 /// SQL语句 482 /// 483 public string Sql { get; set; } 484 485 /// 486 /// 参数数组属性 487 /// 488 public SqlParameter[] Parameter => _mParas.ToArray(); 489 490 /// 491 /// 添加参数 492 /// 493 /// 参数名称 494 /// 参数值 495 public void AddParameter(string name, object value) 496 { 497 _mParas.Add(new SqlParameter(name, value)); 498 } 499 500 /// 501 /// 添加参数数组 502 /// 503 /// 参数数组 504 public void AddParameter(SqlParameter[] paras) 505 { 506 _mParas.AddRange(paras); 507 } 508 } 509 }