导读:在上一篇博客中,介绍了简单的SQLHelper重构,即数据库链接,打开和关闭链接的优化等。现在,将介绍参数化查询和执行命令类型的改造。
一、必要性
1,参数化查询
在上篇博客中,在查询的时候,仅仅通过传入一个SQL语句,比如:insert into category(name) values('hhx'),这样做是可行的,但它会导致一个问题(SQL注入),就是,如果用户输入的是:hhx') delete category where .......更甚至是:hhx') delete from category。这时候,虽然可以插入一条数据,但在其后,又会删除表中的数据。如果真到了这时候,那就真的只有哭的时候了。
有效解决方法之一:参数化查询!
比如,将insert intocategory(name)values(“hhx”)变为insert into category(name) values @name。那么即使我们输入的是:hhx') delete category where ,也不会产生删除数据的情况,而仅仅是插入一条名称为:“hhx') delete category where ” 的记录。
2,命令类型
在SQL执行语句中,我们会常看到:cmd.CommandType = CommandType.Text 或者 cmd.CommandType = CommandType.StoredProcedure,它表示的是执行的SQL语句是哪一种类型,文本型或是存储过程。PS:cmd是SQL的一个命令对象SqlCommand。
如果,我们在每一个方法中都对这个进行说明从而运用函数的重载去达到效果的话,不是不可以,但会相当的费事儿。因为既然利用重载,那么就得对方法再编写一遍。
解决方法之一:引入一个命令类型参数,在用户使用SQL语句时,确定是哪种执行类型。
二、怎样运用
1,执行无参的SQL增删改语句
注:默认的commandtype是text型。
<span style="font-size:18px;"> #region 该方法执行传入的SQL增删改语句(无参)
/// <summary>
/// 该方法执行传入的SQL增删改语句(无参)
/// </summary>
/// <param name="cmdText">要执行的SQL增删改语句或存储过程</param>
/// <param name="ct">命令类型</param>
/// <returns>返回更新的记录数</returns>
public int ExecuteNonQuery(string cmdText, CommandType ct)
{
int res;
try
{
SqlCommand cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
return res;
}
#endregion</span>
2,执行有参的SQL增删改语句
注意:
1,使用using语句段,对于try catch语句的精简。
2,因为在SQL语句中传入的参数为1-N个,所以需要使用数组的形式。即:SQLParameter[]paras和cmd.Parameters.AddRange(paras)的运用。
<span style="font-size:18px;"><span style="font-size:24px;"> #region 执行带参数的SQL增删改语句
/// <summary>
/// 执行带参数的SQL怎删改语句
/// </summary>
/// <param name="cmdText">SQL增删改语句或存储过程</param>
/// <param name="paras">参数集合</param>
/// <param name="ct">命令类型</param>
/// <returns></returns>
public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
int res;
using (cmd = new SqlCommand(cmdText, GetConn()))
{
cmd.CommandType = ct;
cmd.Parameters.AddRange(paras);
res = cmd.ExecuteNonQuery();
}
return res;
}
#endregion</span></span>
三、完整的SQLHelper类
<span style="font-size:18px;">/**********************************************
'类名:SQLHelper
'命名空间:DAL
'创建时间:2015/3/7 16:32:46
'创建人:HXX
'修改时间:
'修改人:
'版本号:4.0.30319.18449
'版权:HHX
'说明:SQLHelper助手类,简化D层增删改查。
**********************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace DAL
{
/// <summary>
/// SQLHelper操作类
/// </summary>
public class SQLHelper
{
private SqlCommand cmd = null;
private SqlDataReader sdr = null;
private SqlConnection conn = null;
#region 通过构造函数,给SQLHelper的属性附初值
/// <summary>
/// 通过构造函数,给SQLHelper的属性附初值
/// </summary>
public SQLHelper()
{
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
conn = new SqlConnection(connStr);
}
#endregion
private SqlConnection GetConn()
{
//如果数据库关闭,则打开
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
return conn;
}
#region 该方法执行传入的SQL增删改语句(无参)
/// <summary>
/// 该方法执行传入的SQL增删改语句(无参)
/// </summary>
/// <param name="cmdText">要执行的SQL增删改语句或存储过程</param>
/// <param name="ct">命令类型</param>
/// <returns>返回更新的记录数</returns>
public int ExecuteNonQuery(string cmdText, CommandType ct)
{
int res;
try
{
SqlCommand cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
return res;
}
#endregion
#region 执行带参数的SQL增删改语句
/// <summary>
/// 执行带参数的SQL怎删改语句
/// </summary>
/// <param name="cmdText">SQL增删改语句或存储过程</param>
/// <param name="paras">参数集合</param>
/// <param name="ct">命令类型</param>
/// <returns></returns>
public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
int res;
using (cmd = new SqlCommand(cmdText, GetConn()))
{
cmd.CommandType = ct;
cmd.Parameters.AddRange(paras);
res = cmd.ExecuteNonQuery();
}
return res;
}
#endregion
#region 该方法执行传入的SQL查询语句(无参)
/// <summary>
/// 该方法执行传入的SQL查询语句(无参)
/// </summary>
/// <param name="cmdText">SQL查询语句或存储过程</param>
/// <param name="ct">命令类型</param>
/// <returns></returns>
public DataTable ExecuteQuery(string cmdText, CommandType ct)
{
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
dt.Load(sdr);
}
return dt;
}
#endregion
#region 执行带参数的SQL查询语句
/// <summary>
/// 执行带参数的SQL查询语句
/// </summary>
/// <param name="cmdText">SQL查询语句或存储过程</param>
/// <param name="paras">参数集合</param>
/// <param name="ct"></param>
/// <returns></returns>
public DataTable ExecuteQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
DataTable dt = new DataTable();
cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
cmd.Parameters.AddRange(paras);
using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
dt.Load(sdr);
}
return dt;
}
#endregion
}
}
</span>
四、学习感受
在这一次的学习中,我总算是把这个SQLHelper给理解了。这之中的学习,不可厚非的会得益于我刚看到这个东西时的初步学习,那时候也是查了很多资料,VB编写的,C编写的,Java编写的都看过,但也都是要懂不懂。脑袋里装了一堆这玩意儿,但就是没有一个是清晰的。很苦恼,幸得师傅指点说先放放,我可能是钻进死胡同了。
现在的感受是:对于学习,初次见面,认识它;再次见面,了解它;三次见面,征服它。