首页 > 代码库 > 简单的web三层架构系统【第二版】

简单的web三层架构系统【第二版】

 

昨天写了 web三层架构的第一版,准确的说是三层架构的前期,顶多算是个二层架构,要慢慢完善。

 

第一版里,程序虽说能运行起来,但是有一个缺陷,就是里面的SQL语句,是使用的拼接字符进行执行。这样安全系数很低,如果有心人的话,可能会SQL注入,重新拼接字符,然后篡改我们的数据库内容,导致不可挽回的损失。

 

在第二版本,也就是这一版里,我对原来的SQL语句进行了重构,使用带参数的SQL语句对数据库进行操作,这样做的好处是,无论用户输入的是什么格式的字符,SQL语句都会原封不动的把这些字符写入到数据库中,这样就避免了有心人对字符进行拼接,导致数据库出错。

 

下面我用另一个小例子来说明防止SQL注入的核心代码,在最后会给出我重构过的第一版程序,也就是今天要写第二版程序:

 

这是DAO类中的insert方法:

 1         public bool insert(string name, string sex, string salary) 2         { 3             bool flag = false; 4  5             SqlParameter[] paras = new 6             { 7                 new SqlParameter("@name", name), 8                 new SqlParameter("@sex", sex), 9                 new SqlParameter("@salary", salary)10             };11 12             string sql = "insert into person ([name], sex, salary) values (@name, @sex, @salary)";13 14             if (sq.ExecuteNonQuery(sql, paras) > 0)    //把SQL语句和SQL参数同时传入SQLHelper的ExecuteNonQuery中执行。15             {                   //16                 flag = true;17             }18 19             return flag;20    }

 

这是SQLHelper类中的ExecuteNonQuery方法:

 1         public int ExecuteNonQuery(string sql, SqlParameter[] paras) 2         { 3             int result; 4  5             cmd = new SqlCommand(sql, getcon());    //创建SQLcommand对象cmd 6  7             cmd.Parameters.AddRange(paras);         //在SQLcommand对象cmd中,添加参数。 8                               //上面的这一句注释,是自己的理解,如果理解错了,请在评论区帮忙指正一下,先谢过。 9             result = cmd.ExecuteNonQuery();         //然后执行对象cmd,其中已经包含了SQL语句和要用的参数10 11             return result;12       }

 

上面是一个小例子,创建了一张表,然后向表里的 NAME SEX SALARY 三个字段中添加内容。

 

 

 

下面是第二版web三层架构程序:

 

SQLhelper助手类:

  1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6   7 using System.Data;  8 using System.Data.SqlClient;  9 using System.Configuration; 10  11 namespace DAL 12 { 13     public class SQLHelper 14     { 15         SqlCommand cmd = null; 16  17         public string strcon() 18         { 19             string strcon = ConfigurationManager.ConnectionStrings["strcon"].ConnectionString; 20  21             return strcon; 22         } 23  24         public SqlConnection getcon() 25         { 26             SqlConnection con = new SqlConnection(strcon()); 27  28             if (con.State == ConnectionState.Closed) 29             { 30                 con.Open(); 31             } 32  33             return con; 34         } 35  36         #region 执行增删改查的SQL语句 37         /// <summary> 38         /// 执行增删改查的SQL语句 39         /// </summary> 40         /// <param name="sql">要执行的SQL</param> 41         /// <returns>返回执行SQL语句后影响的行数</returns> 42         public int ExecuteNonQuery(string sql) 43         { 44             int res; 45  46             try 47             { 48                 cmd = new SqlCommand(sql, getcon()); 49  50                 res = cmd.ExecuteNonQuery(); 51             } 52             catch (Exception ex) 53             { 54                 throw ex; 55             } 56             finally 57             { 58                 if (getcon().State == ConnectionState.Open) 59                 { 60                     getcon().Close(); 61                 } 62             } 63  64             return res; 65         } 66         #endregion 67  68         #region 执行带参数的增删改SQL语句 69         /// <summary> 70         /// 执行带参数的增删改SQL语句 71         /// </summary> 72         /// <param name="sql">要执行的SQL语句</param> 73         /// <param name="paras">传入的参数</param> 74         /// <returns>返回受影响的行数</returns> 75         public int ExecuteNonQuery(string sql, SqlParameter[] paras)//上下两个ExecuteNonQuery因为使用了方法的重载,其中参数不同,所以虽说都在调用ExecuteNonQuery,但是传递的参数的个数不同,系统会自动识别用哪一个ExecuteNonQuery方法。 76         { 77             int res; 78  79             cmd = new SqlCommand(sql, getcon());//  1   80  81             cmd.Parameters.AddRange(paras);//  2   84  85             res = cmd.ExecuteNonQuery(); 86  87             return res; 88         } 89         #endregion 90  91         #region 执行传入的SQL查询语句 92         /// <summary> 93         /// 执行传入的SQL查询语句 94         /// </summary> 95         /// <param name="sql">要执行的查询SQL</param> 96         /// <returns>返回查询SQL语句的数据集</returns> 97         public DataTable ExecuteQuery(string sql) 98         { 99             DataTable dt = new DataTable();100 101             //创建一个SqlCommand对象cmd,让其连接数据库,并指向sql语句。//自己理解,如果不对的话请在评论区指正,先谢过。102             cmd = new SqlCommand(sql, getcon());103 104             //执行cmd连接的数据库.使用using后在执行完毕后,直接关闭sdr。不需要写sdr.closed.105             using (SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))//如果使用 CommandBehavior.CloseConnection 参数,那么在代码的结尾处就不需要写 getcon().Close(),他会直接关闭。106             {107                 dt.Load(sdr);// Load 这种方法适合于SqlDataReader。如果是SqlDataAdapter,则会用到 Fill 方法。108             }109 110             return dt;111         }112         #endregion113 114         #region 执行传入带参数的SQL查询语句115         /// <summary>116         ///  执行传入带参数的SQL查询语句117         /// </summary>118         /// <param name="sql">要执行的SQL语句</param>119         /// <param name="paras">传入的参数</param>120         /// <returns>返回查询的数据集</returns>121         public DataTable ExecuteQuery(string sql, SqlParameter[] paras)122         {123             DataTable dt = new DataTable();124 125             cmd = new SqlCommand("sql", getcon());126 127             cmd.Parameters.AddRange(paras);128 129             using (SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))130             {131                 dt.Load(sdr);132             }133 134             return dt;135         }136         #endregion137     }138 }

 

 

personDAO员工操作类:

  1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6   7 using System.Data;  8 using System.Data.SqlClient;  9  10 namespace DAL 11 { 12     public class personDAO 13     { 14         SQLHelper sq = null; 15  16         public personDAO() 17         { 18             sq = new SQLHelper(); 19         } 20  21         #region 增加员工信息 22         /// <summary> 23         /// 增加员工信息 24         /// </summary> 25         /// <param name="name">要添加的员工姓名</param> 26         /// <param name="sex">要添加的员工性别</param> 27         /// <param name="salary">要添加的员工工资</param> 28         /// <returns>返回真假值:如果是真显示添加成功,如果是假显示添加失败</returns> 29         public bool insert(string name, string sex, string salary) 30         { 31             bool flag = false; 32  33             SqlParameter[] paras = new SqlParameter[] 34             { 35                 new SqlParameter("@name", name), 36                 new SqlParameter("@sex", sex), 37                 new SqlParameter("@salary", salary) 38             }; 39  40             string sql = "insert into person ([name], sex, salary) values (@name, @sex, @salary)";//记住,添加参数的时候,不需要 双引号 或是 单引号。 41  42             if (sq.ExecuteNonQuery(sql, paras) > 0)//把sql语句和所用到参数数组,一起传送到 ExecuteNonQuery 中去执行。 43             { 44                 flag = true; 45             } 46  47             return flag; 48         } 49         #endregion 50  51         #region 删除员工信息 52         /// <summary> 53         /// 删除员工信息 54         /// </summary> 55         /// <param name="id">要删除员工的id</param> 56         /// <returns>返回真假值:如果是真显示删除成功,如果是假显示删除失败</returns> 57         public bool delete(string id) 58         { 59             bool flag = false; 60  61             SqlParameter[] paras = new SqlParameter[] 62             { 63                 new SqlParameter("@id", id) 64             }; 65  66             string sql = "delete from person where id = @id";//记住,添加参数的时候,不需要 双引号 或是 单引号。 67  68             if (sq.ExecuteNonQuery(sql, paras) > 0) 69             { 70                 flag = true; 71             } 72  73             return flag; 74         } 75         #endregion 76  77         #region 更改员工信息 78         /// <summary> 79         /// 更改员工信息 80         /// </summary> 81         /// <param name="id">要更改的员工编号</param> 82         /// <param name="name">要更改的员工姓名</param> 83         /// <param name="sex">要更改的员工性别</param> 84         /// <param name="salary">要更改的员工工资</param> 85         /// <returns>返回真假值:如果是真显示更改成功,如果是假显示更改失败</returns> 86         public bool update(string id, string name, string sex, string salary) 87         { 88             bool flag = false; 89  90             SqlParameter[] paras = new SqlParameter[]//创建参数数组 91             { 92                 new SqlParameter("@id", id),//我的理解:对参数数组赋值 93                 new SqlParameter("@name", name), 94                 new SqlParameter("@sex", sex), 95                 new SqlParameter("@salary", salary) 96             }; 97  98             //使用参数数组 99             string sql = "update person set [name] = @id, sex = @name, salary = @sex where id = salary";//记住,添加参数的时候,不需要 双引号 或是 单引号。100 101             if (sq.ExecuteNonQuery(sql, paras) > 0)102             {103                 flag = true;104             }105 106             return flag;107         }108         #endregion109 110         #region 判断员工姓名是否重复111         /// <summary>112         /// 判断员工姓名是否重复113         /// </summary>114         /// <param name="name">要进行判断的员工姓名</param>115         /// <returns>返回真假值:如果是真代表重复,如果是假进行添加</returns>116         public bool repeat(string name)117         {118             bool flag = false;119 120             SqlParameter[] paras = new SqlParameter[]121             {122                 new SqlParameter("@name", name)123             };124 125             string sql = "select * from person where [name] = @name";//记住,添加参数的时候,不需要 双引号 或是 单引号。126 127             #region 下面这样写的话,还要重新建立一张虚拟表,如果直接用下面的方法,进行行数的判断就不需要建立。128             //DataTable dt = sq.ExecuteQuery(sql);129 130             //if (dt.Rows.Count > 0)//dt.Rows.Count 这个方法是检查返回的虚拟表中是不是有数据,如果有的话则行数不为零。如果没有的话则行数为零。131             //{132             //    flag = true;133             //}134             #endregion135 136             if (sq.ExecuteQuery(sql, paras).Rows.Count > 0)//dt.Rows.Count 这个方法是检查返回的虚拟表中是不是有数据,如果有的话则行数不为零。如果没有的话则行数为零。137             {138                 flag = true;139             }140 141             return flag;142         }143         #endregion144     }145 }

 

 

上面就是重构的第一版的代码,也就是第二版,其中如果有错误的地方,请在评论区帮忙指正,先谢过了大家。

 

简单的web三层架构系统【第二版】