C#连接SQL-Server数据库超详细讲解以及防SQL注入

发布于:2025-08-30 ⋅ 阅读:(14) ⋅ 点赞:(0)

C#连接SQL Server数据库完整指南,整合了ADO.NET原生连接与Entity Framework Core两种实现方式。

这篇文件详细介绍C#代码连接

数据库的通用操作
 数据库链接功能 数据库的增删改查操作

  1 配置全局数据库链接字符串 App.config
  2 获取数据库链接字符串

先在App.config配置连接字符串

<connectionStrings>
    //name 自定义名称  服务器名称Server=ip地址 端口号;数据库名称 账号-密码
    <add name="c1" connectionString="Server=.,1433;DataBase=SMDB;Uid=sa;Pwd=123456"/>
</connectionStrings>

server=.:指定服务器名称为 .(自己计算机),表示数据库服务器位于本地计算机上。.用于指代本地主机。

database=SMDB:指定要连接的数据库名称为 SMDB。这意味着连接成功后,将在 SMDB数据库上执行数据库操作。

uid=sa:指定用户身份验证使用的用户名为 sasa 是 SQL Server 中的系统管理员账户。

pwd=123456:指定用户身份验证使用的密码为 123456

   //获取
public static readonly string connstring = ConfigurationManager.ConnectionStrings["c1"].ToString();

注:也可以在c#创建字符串来设置连接字符串在进行获取

 * 执行sql命令几个方法
 * 1 cmd.ExCuteNonQuery 添加数据(insert into) 修改数据update 删除数据delete
 * 2 cmd.ExcuteScalar   select count(*)
 * 3 cmd.ExcuteReader   返回的是sqlDatareader 管道 需要使用while循环, select *
 * 4 SqlDataAdapter da = new DataAdapter(cmd) ,select * 场景

展示案例

获取单一结果的方法 列如 记录个数等功能

//获取单一结果的方法 列如 记录个数等功能
public static object GrSigleResult(string sql)
{
    //1创建数据库连接 
    SqlConnection=new SqlConnection(connstring);
    //2创建sql命令
    SqlCommand cmd=new SqlCommand(sql,conn)
    //打开连接执行命令
     try
     {
         conn.open();
         return cmd.ExecuteScalar();
      }
    catch(Exception){throw;}
    finally{conn.Close();}
}

方法调用:
  // 获取总人数
  public static int GetStudentCount()
  {
      string sql = "select count(*) from Students";
      return Convert.ToInt32(SQLHelper.GrtSigleResult(sql));
  }

执行增删改查操作

//执行增删改查操作
public static int Update(string sql)
{
   SqlConnection conn=new SqlConnection(connstring);
   SqlCommand cmd=new SqlCommand(sql,conn);
    try
     {
         conn.open();
         return cmd.ExecuteNonQuery();
      }
    catch(Exception){throw;}
    finally{conn.Close();}
}
方法调用:
public static bool ClockInSuccess(Attendance ad)
{
    string sql = "insert into Attendance(CarNo) Values('{0}')";
    sql = string.Format(sql,ad.CardNo);
    try
    {
        SQLHelper.Update(sql);
        return true;
    }
    catch (Exception)
    {

        throw;
    }
}

SqlDataReader 存储数据库数据 获取数据的所有记录 要用while循环去读

 public static SqlDataReader GetReader(string sql)
  {
      SqlConnection conn = new SqlConnection(connstring);
      SqlCommand cmd = new SqlCommand(sql,conn);
      try
      {
          conn.Open();
          return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
      }
      catch (Exception)
      {
          throw;
      }
  }
方法调用:
    1 返回的是对象类型
     public static Student GetStudentByCardNo(string cardNo)
 {
     string sql = "select StudentId,StudentName,Gender,Birthday,StudentIdNo,PhoneNumber,ClassName,StudentAddress,CardNo,StuImage from Students ";
     sql += "inner join StudentClass on Students.ClassId = StudentClass.ClassId ";
     sql += "where CardNo = '{0}'";
     sql = string.Format(sql, cardNo);
     SqlDataReader r = SQLHelper.GetReader(sql);
     Student student = null;
     if (r.Read())
     {
         student = new Student()
         {
             StudentId = Convert.ToInt32(r["StudentId"]),
             StudentName = r["StudentName"].ToString(),
             Gender = r["Gender"].ToString(),
             BirthDay = Convert.ToDateTime(r["Birthday"]),
             StudentIdNo = r["StudentIdNo"].ToString(),
             PhoneNumber = r["PhoneNumber"].ToString(),
             ClassName = r["ClassName"].ToString(),
             StudentAddress = r["StudentAddress"].ToString(),
             CarNo = r["CardNo"].ToString(),
             StuImage = r["StuImage"] == null ? "" : r["StuImage"].ToString(),
         };

     }
     r.Close();
     return student;
 }
2返回list集合
     public static List<Student> GetScoreList(string cname)
 {
     //全校成绩
     string sql = "select Students.StudentId, StudentName,ClassName,Gender,CSharp,SqlserverDB from Students inner join ScoreList on Students.StudentId=ScoreList.StudentId inner join StudentClass on StudentClass.ClassId = Students.ClassId ";

     if (cname != null && cname.Length != 0)
     {
         //按照班级查询
         sql += "where ClassName = '" + cname + "'";

     }
     SqlDataReader r = SQLHelper.GetReader(sql);
     List<Student> list = new List<Student>();
     while (r.Read())
     {
         list.Add(new Student()
         {
             StudentId = Convert.ToInt32(r["StudentId"]),
             StudentName = r["StudentName"].ToString(),
             Gender = r["Gender"].ToString(),
             ClassName = r["ClassName"].ToString(),
             CSharp = Convert.ToInt32(r["CSharp"]),
             SqlserverDB = Convert.ToInt32(r["SqlserverDB"]),

         });
     }
     r.Close();
     return list;
 }

获取所有的记录 返回的是dataset数据类型 不要逐条给实体类字段进行赋值

public static DataSet GetDateSet(string sql)
{
     SqlConnection conn = new SqlConnection(connstring);
     SqlCommand cmd = new SqlCommand(sql,conn);
     DataSet ds=new DataSet();
     SqlDataAdapter da=new SqlDataAdapter(cmd)
    try
     {
       conn.Open();
       da.Fill(ds); // 把数据表数据填充在dataset集合中
       return ds;
     }
    catch (Exception)
     {

       throw;
     }
     finally { conn.Close() ; } 
}
方法调用:
 /// <summary>
 /// 获取所有成绩的方法
 /// </summary>
 /// <returns></returns>
 public static DataSet GetAllScore()
 {
     string sql = "select Students.StudentId,StudentName,ClassName,Gender,PhoneNumber,CSharp,SqlserverDB from ScoreList inner join Students on Students.StudentId = ScoreList.StudentId inner join StudentClass on StudentClass.ClassId = Students.ClassId";
     return SQLHelper.GetDateSet(sql);
 }
Ui:
 private DataSet ds = null; // 放置所有的成绩 数据集
   this.ds = ScoreService.GetAllScore();

获取服务器时间

 public static DateTime GetDateTime()
 {
     return Convert.ToDateTime(GrtSigleResult("select getdate()"));
 }
方法调用:
  DateTime t0 = Convert.ToDateTime(SQLHelper.GetDateTime().ToShortDateString());
 public static bool UpdateDBFormExcelByShiWu(List<string> list)
 {
     SqlConnection conn = new SqlConnection(connstring);
     SqlCommand cmd = new SqlCommand();
     cmd.Connection = conn;
     try
     {
         conn.Open();
         // 开启事物
         cmd.Transaction = conn.BeginTransaction();

         // 把list里面指令添加事务中
         foreach (string s in list)
         {
             cmd.CommandText = s;
             cmd.ExecuteNonQuery();
         }
         cmd.Transaction.Commit();
         return true;
     }
     catch (Exception ex)
     {
         MessageBox.Show("添加失败," + ex);
         return false;
     }
     finally
     {
         conn.Close();
     }
 }
方法调用:
  public static bool SaveDataToDB(List<Student> list)
  {
      // 定义sql语句
      StringBuilder sql = new StringBuilder("insert into Students ");
      sql.Append("(StudentName,Gender,BirthDay,StudentIdNo,CardNo,Age,PhoneNumber,StudentAddress,ClassId) ");
      sql.Append("values ");
      sql.Append("('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}');");

      // 2 创建一个保存sql语句的集合
      List<string> sqlList = new List<string>();

      // 3 遍历传递过来的学生集合对象
      int i = 1213;
      foreach (Student student in list)
      {
          string s = string.Format(sql.ToString(), student.StudentName, student.Gender,
              student.BirthDay.ToString("yyyy-MM-dd"), student.StudentIdNo, student.CarNo+i, student.Age,
              student.PhoneNumber, student.StudentAddress, student.ClassId);
          sqlList.Add(s);
          i++;
      }
      return SQLHelper.UpdateDBFormExcelByShiWu(sqlList);
  }

SQL注入

当我们要在登录账号密码时 不知道账号密码 可以字符串拼接 直接登录 或一些其他删除表等操作

比如用户输入: ' or 1=1 -- 就可以成功登录了'是跟前面输入的sql语句连接 or 1=1 当条件成立时 然后就可以成功登录 --是省略后面的 甚至可以执行删库的操作: '; drop database xxxx

防止sql注入的方法就是避免直接将用户输入的内容拼接到sql语句中

使用带参数的sql语句执行数据库操作就可以避免sql注入

使用带参数的sql语句不需要关注sql语句带引号的问题

在sql语句中 使用@xxx 定义sql参数

案列:

// 2、在SqlCommand对象中为sql参数赋值

        // 添加参数的方法1(推荐)
        // cmd.Parameters.AddWithValue("@abc", textBox1.Text);           // 添加一个参数,并为参数赋值
        // cmd.Parameters.AddWithValue("@efg", textBox2.Text);

        // 添加参数的方法2
        //cmd.Parameters.Add("@abc", SqlDbType.VarChar);      // 添加一个参数,并指定参数的类型
        //cmd.Parameters["@abc"].Value = textBox1.Text;       // 为@abc参数赋值
        //cmd.Parameters.Add("@efg", SqlDbType.VarChar);
        //cmd.Parameters["@efg"].Value = textBox2.Text;

        // 添加参数的方法3
        //cmd.Parameters.Add(new SqlParameter("@abc", textBox1.Text));
        //cmd.Parameters.Add(new SqlParameter("@efg", textBox2.Text));

        // 添加参数的方法4(推荐)
        SqlParameter[] parameters = new SqlParameter[]
        {
            new SqlParameter("@abc", textBox1.Text),
            new SqlParameter("@efg", textBox2.Text)
        };
        cmd.Parameters.AddRange(parameters);
        
        封装几个类的方法
        
             /// <summary>
     /// 执行增删改操作
     /// </summary>
     /// <param name="sql">要执行的sql语句</param>
     /// <param name="parameter">传递的sql参数</param>
     /// <returns></returns>
     public static int Update(string sql, params SqlParameter[] parameter)
     {
         SqlCommand cmd = new SqlCommand(sql, conn);

         cmd.Parameters.AddRange(parameter);

         return cmd.ExecuteNonQuery();
     }

     /// <summary>
     /// 执行查询操作
     /// </summary>
     /// <param name="sql">要执行的sql语句</param>
     /// <param name="parameter">传递的sql参数</param>
     /// <returns></returns>
     public static SqlDataReader GetData(string sql, params SqlParameter[] parameter)
     {
         SqlCommand cmd = new SqlCommand(sql, conn);

         cmd.Parameters.AddRange(parameter);

         return cmd.ExecuteReader();
     }
     
     /// <summary>
     /// 执行单行单列的查询操作
     /// </summary>
     /// <param name="sql">要执行的sql语句</param>
     /// <param name="parameter">传递的sql参数</param>
     /// <returns></returns>
     public static object GetObject(string sql, params SqlParameter[] parameter)
     {
         SqlCommand cmd = new SqlCommand(sql, conn);

         cmd.Parameters.AddRange(parameter);

         return cmd.ExecuteScalar();
     }

下一节讲EF(Entity Framework) 不需要写连接字符串 因为在写字符串也很难查找报错地方因为字符串写错问题 以及连接创建许多代码 和查询等还需要注意SQL防注入 


网站公告

今日签到

点亮在社区的每一天
去签到