为了更快捷的反问数据库,以及更加符合面向对象封装的原则,我们应该有一个自己的数据库操作类,SqlHelper.cs 这样我们在访问数据库的时候就不必每一次都连接、赋值、执行了,可以比较方便的一步到位。
首先书写一个比较简易的SqlHelp.cs,分开写ExecuteNonQuery、ExecuteScalar、ExecuteReader。
◇首先配置连接变量(上一节中有说到)
private static string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
◇SqlHelper.cs中的ExecuteNonQuery():
public static int ExecuteNonQuery(string sql) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; return cmd.ExecuteNonQuery(); } } }
◇其中:
①为了其他的文件方便调用,这里全部将自写的方法设置为静态方法(可以不实例化直接调用,下同)
②系统自带的ExecuteNonQuery()方法的返回值是一个int类型,返回的是数据库中所受影响的行数。
◇SqlHelper.cs中的ExecuteScalar():
public static object ExecuteScalar(string sql) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; return cmd.ExecuteScalar(); } } }
◇这个和上面的ExecuteNonQuery()没有太多差别,唯一不同的是函数类型,系统自带的ExecuteScalar()是范围一个一行一列的查询结果,可能有多种变量类型,所以我们在这里把它的类型定义为object,等到需要用到的时候再进行类型转换。
◇SqlHelper.cs中的ExecuteDataTable():(也就是ExecuteRead()方法的返回集合表)
public static DataTable ExecuteDataTable(string sql) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; SqlDataAdapter da = new SqlDataAdapter(cmd); DataSet ds = new DataSet(); da.Fill(ds); DataTable dt = ds.Tables[0]; return dt; } } }
◇试着写一个按钮Click事件来测试一下ExecuteDataTable(),证明手写简易SqlHelper无误。
private void button2_Click(object sender, RoutedEventArgs e) { DataTable dt = SqlHelper.ExecuteDataTable("select * from Student"); foreach (DataRow dr in dt.Rows) { string name = (string)dr[0]; MessageBox.Show(name); } }
接下来将对上面所写的简易Sqlhelper的不足之处进行改进:
◇这个改进主要是在对于sql语句中的一些关键参数的输入进行改进。避免进行拼接字符串造成注入漏洞攻击。
◇首先引入“可变长度参数”这个关键字符串“params”这个关键字。这个关键字只能放在定义函数的最后一个参数之前。
◇然后对ExecuteNonQuery()方法进行改进:
public static int ExecuteNonQuery(string sql,params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return cmd.ExecuteNonQuery(); } } } public static object ExecuteScalar(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } } } public static DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); SqlDataAdapter adapter = new SqlDataAdapter(cmd); DataSet dataset = new DataSet(); adapter.Fill(dataset); return dataset.Tables[0]; } } }
◇说明:cmd.Parameters.AddRange(parameters); 这一句话相当于把SqlParameter[]这个数组 内的parameters全部加入到cmd中去。
下面试着写一段代码来证明上述代码无误。
private void button3_Click(object sender, RoutedEventArgs e) { DataTable dt = SqlHelper.ExecuteDataTable("select * from Student where name = @name",new SqlParameter("@name","xuweixi")); foreach (DataRow dr in dt.Rows) { string name = (string)dr[0]; MessageBox.Show(name); } }
◇这样就完成了SqlHelper.cs改进版本的编写了。