当前位置: 首页 > news >正文

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

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防注入 

http://www.xdnf.cn/news/1387423.html

相关文章:

  • 零基础json入门教程(基于vscode的json配置文件)
  • 序列化和反序列的学习
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(五)
  • Word - Word 查找文本中的特定内容
  • Redis vs Elasticsearch:核心区别深度解析
  • c++二叉搜索树
  • 在Linux的环境下安装GitLab(保姆级别)
  • Ubuntu下的压缩及解压缩
  • Llama-index学习文档
  • AI驱动万物智联:IOTE 2025深圳展呈现无线通信×智能传感×AI主控技术融合
  • 【Python办公】CSV按列去重工具
  • LangChain实战(三):深入理解Model I/O - Prompts模板
  • 聊聊Prompt Engineering (提示词工程)
  • Rust Web框架Axum学习指南之响应和异常封装
  • websocket建立连接过程
  • AI供应链优化+AI门店排班:蜜雪冰城降本20%、瑞幸提效的AI商业落地实战
  • 港科大开放世界长时域具身导航!LOVON:足式机器人开放词汇目标导航
  • LeetCode Hot 100 Python (1~10)
  • 1 分钟 Maya 动画渲染要多久?5 天还是 5 小时
  • linux系统学习(15.启动管理)
  • 第一百零二章:AI的“未来电影制片厂CEO”:多模态系统落地项目实战(完整 AI 视频创作平台)
  • 极飞科技AI智慧农业实践:3000亩棉田2人管理+产量提15%,精准灌溉与老农操作门槛引讨论
  • 组件的生命周期:`useEffect` 的威力与副作用处理
  • 随机森林的 “Bootstrap 采样” 与 “特征随机选择”:如何避免过拟合?(附分类 / 回归任务实战)
  • 华为云CCE的Request和Limit
  • Ethercat主从站移植时的问题记录(二)—无法进入OP状态且从站PDI中断不触发
  • 什么是Jmeter? Jmeter工作原理是什么?
  • linux上安装methylkit -- 安全下车版 (正经版: Linux环境下安装methylKit的实践与避坑指南)
  • springboot java开发的rocketmq 顺序消息保证
  • CAN总线(Controller Area Network Bus)控制器局域网总线(二)