ADO.NET进阶

一、sql注入风险及解决方案

SQL注入是指在事先定义好的SQL语句中注入额外的SQL语句,从此来欺骗数据库服务器的行为。

示例:制作会员登录功能。

二、防止sql注入解决方案

  • 使用参数化查询
  • 使用ORM框架 Entity Framework可以自动处理SQL查询的安全性

使用参数化查询

cs 复制代码
private void btLogin_Click(object sender, EventArgs e)
{
    // 定义数据库连接字符串
    string conStr = "server=.;database=adoNet;uid=sa;pwd=123456";    
    // 创建SqlConnection对象并初始化连接字符串
    SqlConnection conn = new SqlConnection(conStr);    
    // 打开数据库连接
    conn.Open();
    
    // 定义SQL查询语句,并使用参数化查询防止SQL注入
    string sql = " select * from Member where MemberAccount = @MemberAccount and MemberPwd = @MemberPwd";
    // 创建一个SqlDataAdapter对象,用于填充DataTable
    SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
    
    // 向SelectCommand中添加参数,将文本框中的值作为参数值传递
    adapter.SelectCommand.Parameters.Add(new SqlParameter("@MemberAccount", this.textAccount.Text));
    adapter.SelectCommand.Parameters.Add(new SqlParameter("@MemberPwd", this.textPwd.Text));
    
    // 创建一个新的DataTable实例
    DataTable dt = new DataTable();
    
    // 使用SqlDataAdapter的Fill方法填充DataTable
    adapter.Fill(dt);
        
    if (dt.Rows.Count > 0)           
        MessageBox.Show("登录成功");    
    else    
        MessageBox.Show("登录失败");
    
}
cs 复制代码
string sql ="INSERT INTO Member (MemberAccount, MemberPwd, MemberName, MemberPhone)VALUES" +
     " (@MemberAccount ,@MemberPwd ,@MemberName ,@MemberPhone )";
 //****执行sql语句******
 SqlCommand cmd = new SqlCommand(sql, conn);
 cmd.Parameters.Add(new SqlParameter("@MemberAccount", this.textAccount.Text));
 cmd.Parameters.Add(new SqlParameter("@MemberPwd", this.textPwd.Text));
 cmd.Parameters.Add(new SqlParameter("@MemberName", this.textName.Text));
 cmd.Parameters.Add(new SqlParameter("@MemberPhone", this.textIphone.Text));
 int code = cmd.ExecuteNonQuery();

三、封装DBHelper类

  • 代码重用
  • 提高可读性和可维护性
  • 遵循单一职责原则
  • 安全性参数化查询
cs 复制代码
internal class DBHelper
{
    // 连接字符串,包含服务器地址、数据库名称、用户名和密码
    public static string strConn = "server=.;database=adoNet;uid=sa;pwd=123456";

    // 数据库连接对象,用于与数据库建立连接
    public static SqlConnection conn = null;

    // 数据适配器,用于执行 SQL 命令并填充数据集
    public static SqlDataAdapter adp = null;

    /// <summary>
    /// 打开数据库连接
    /// </summary>
    public static void OpenConn()
    {
        if (conn == null)
        {
            // 如果连接对象为空,则创建一个新的连接对象并打开连接
            conn = new SqlConnection(strConn);
            conn.Open();
        }
        if (conn.State == System.Data.ConnectionState.Closed)
        {
            // 如果连接已关闭,则重新打开连接
            conn.Open();
        }
        if (conn.State == System.Data.ConnectionState.Broken)
        {
            // 如果连接状态为断开,则先关闭再重新打开连接
            conn.Close();
            conn.Open();
        }
    }

    /// <summary>
    /// 准备 SQL 语句,包括打开数据库连接和创建数据适配器
    /// </summary>
    /// <param name="sql">要执行的 SQL 语句</param>
    public static void PrepareSql(string sql)
    {
        OpenConn(); // 打开数据库连接
        adp = new SqlDataAdapter(sql, conn); // 创建数据适配器并设置 SQL 语句和连接对象
    }

    /// <summary>
    /// 设置 SQL 语句的参数
    /// </summary>
    /// <param name="paramenterName">参数名称</param>
    /// <param name="paramenterValue">参数值</param>
    public static void SetParamenter(string paramenterName, object paramenterValue)
    {
        if (paramenterValue == null)
        {
            // 如果参数值为 null,则将其转换为 DBNull.Value
            paramenterValue = DBNull.Value;
        }// 添加参数到 SQL 命令中
        adp.SelectCommand.Parameters.Add(new SqlParameter(paramenterName, paramenterValue)); 
    }

    /// 执行非查询 SQL 语句(如 INSERT、UPDATE、DELETE)
    public static int ExecNonQuery()
    {
        int count = adp.SelectCommand.ExecuteNonQuery(); // 执行 SQL 命令并返回受影响的行数
        conn.Close(); // 关闭数据库连接
        return count;
    }

  
    /// 执行查询 SQL 语句并返回数据表
    public static DataTable ExceQuery()
    {
        DataTable dt = new DataTable(); // 创建一个新的数据表
        adp.Fill(dt); // 使用数据适配器填充数据表
        return dt; // 返回数据表
    }

    // 执行查询 SQL 语句并返回 DataReader 对象
    //<returns>包含查询结果的 DataReader 对象</returns>
    public static SqlDataReader ExcuDataReader()
    {// 执行 SQL 命令并返回 DataReader 对象,同时设置关闭连接的行为
        return adp.SelectCommand.ExecuteReader(CommandBehavior.CloseConnection); 
    }

    /// <summary>
    /// 执行查询 SQL 语句并返回单个值
    /// </summary>
    /// <returns>查询结果的第一个值</returns>
    public static Object ExecuteScalar()
    {
        Object obj = adp.SelectCommand.ExecuteScalar(); // 执行 SQL 命令并返回第一个值
        conn.Close(); // 关闭数据库连接
        return obj; // 返回查询结果
    }
}
cs 复制代码
private void button1_Click(object sender, EventArgs e)
 {   //准备sql语句
     string sql = "INSERT INTO Member (MemberAccount, MemberPwd, MemberName, MemberPhone)VALUES" +
         " (@MemberAccount ,@MemberPwd ,@MemberName ,@MemberPhone )";
     DBHelper.PrepareSql(sql);

     //传参数
     DBHelper.SetParamenter("@MemberAccount", this.textAcount.Text);
     DBHelper.SetParamenter("@MemberPwd", this.textPwd.Text);
     DBHelper.SetParamenter("@MemberName", this.textName.Text);
     DBHelper.SetParamenter("@MemberPhone", this.textIphone.Text);
     //执行
     DBHelper.ExecNonQuery();
 }
相关推荐
IvorySQL29 分钟前
PG 日报|优化缓冲区批量扫描,降低多套接字并发竞争
数据库·人工智能·postgresql·开源·区块链
这个DBA有点耶34 分钟前
交易型数据库是什么?OLTP核心能力与2026选型指南
数据库·数据仓库·sql·database·数据库架构·olap·dba
冰封之寂1 小时前
Docker 资源管理终极指南:CPU、内存与 IO 的精细化控制
linux·运维·服务器·docker·云计算
大熊猫侯佩1 小时前
WWDC26 全新 SwiftData 的 .codable 宏选项:它不是泛型专用胶水
数据库·swift·apple
云计算磊哥@2 小时前
运维开发宝典058-大型网站nginx服务器管理全集4
服务器·nginx·运维开发
童谣13 小时前
越华环保集团市级统筹申报数字化中台:政策校验与减排仿真一体化架构
数据库·架构
制造数据与AI践行者老蒋3 小时前
离谱!PromptTemplate 遇上 JSON,花括号直接引发解析战争
数据库·microsoft·json
中微极客3 小时前
用LangChain 0.3构建生产级RAG与Agent:从API集成到Streamlit部署
数据库·人工智能·langchain
吴声子夜歌3 小时前
MongoDB 4.x——并发优化
数据库·mongodb
酷可达拉斯3 小时前
Linux操作系统-shell编程之Grep与正则表达式
linux·运维·服务器·正则表达式·centos