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.pswp.cn/pingmian/94763.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pico2‑ICE FPGA 开发板:从开箱到跑通示例的全历程

FPGA 和 MCU 结合的开发板不多&#xff0c;而 Pico2‑ICE 则把小巧、灵活和易上手完美结合。搭载 RP2350 双核 RISC-V MCU Lattice iCE40UP5K FPGA&#xff0c;配合官方 SDK&#xff0c;你可以一步步跑通各种示例&#xff0c;从 LED 到 VGA&#xff0c;再到 MCU 与 FPGA 协作应…

Java图形图像处理【Swing图像拖拽】【五】

Java图形图像处理【Swing图像拖拽】 18.3.3 Swing图像对象拖拽功能 18.3.3 Swing图像对象拖拽功能 上文讨论的是java.awt.dnd包中提供的拖拽API接口&#xff0c;也可称之为AWT组件的拖拽功能。下面我们要讨论的是Swing框架的拖拽功能&#xff1a;Swing组件也提供了对拖拽功能的…

状态模式与几个经典的C++例子

1. 状态模式定义与核心思想 状态模式解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。通过将状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。 核心思想: 状态抽象:将对象的每个状态都封装到一个独立的类中。 委托代替条件判断:…

SyncBackPro 备份及同步软件中的脚本功能简介

脚本提供了一种灵活而简单的方法来自动执行任务和扩展应用程序的功能。脚本是一个小程序&#xff0c;能够自定义和控制备份作业。例如&#xff0c;用户可以编写脚本来复制、重命名或删除特定文件、自定义用户界面或更改配置文件设置。SyncBackPro 的脚本功能类似于 Microsoft O…

部署2.516.2版本的jenkins,同时适配jdk8

&#x1f4cc; 前言 在企业级开发中&#xff0c;我们常常面临 新老项目并存 的复杂局面&#xff1a; 老项目基于 JDK 8 开发&#xff0c;短期内无法升级&#xff1b; 新项目采用 JDK 17&#xff08;LTS&#xff09;甚至更高版本&#xff1b; 而作为 CI/CD 核心的 Jenkins&#…

Autodesk Maya 2026.2 全新功能详解:MotionMaker AI 动画、LookdevX 材质增强、USD 工作流优化

软件介绍 Autodesk Maya 2026.2是一款专业的3D计算机图形软件&#xff0c;它为数字内容创作者提供了丰富的工具集&#xff0c;以实现高质量的建模、动画、模拟和渲染。该版本带来了多项性能优化和工作流程改进&#xff0c;特别是针对生成式动画工具MotionMaker进行了重大升级&…

STM32之DMA详解

一、DMA 1. DMA的引入 在嵌入式系统或计算机系统中&#xff0c;数据的传输和处理是非常重要的操作。以下通过一个简单的示例来展示传统数据操作方式与 DMA 引入的必要性&#xff1a; int a 10; int b 20;a b;上述代码包含了变量定义、初始化以及变量数据赋值操作。在传统…

链表有环找入口节点原理

环形链表入口检测算法数学解释 数学原理假设定义: 链表头到环入口的距离为 a环入口到相遇点的距离为 b相遇点到环入口的距离为 c环的长度为 b c第一次相遇时: 慢指针走了 s a b 步快指针走了 f a b n(b c) 步&#xff0c;其中 n 是快指针在环内转的圈数由于快指针速度是…

Java 基本类型与包装类详解

Java 基本类型与包装类详解 在 Java 开发中&#xff0c;理解 基本数据类型与包装类、字符串处理、以及高精度计算类是非常核心的能力。这不仅关系到程序性能&#xff0c;还影响代码的正确性和可维护性。本文将详细讲解这些知识点&#xff0c;并给出常见的使用技巧和陷阱。 1️…

CRYPT32!CryptMsgUpdate函数分析之CRYPT32!PkiAsn1Decode函数的作用是得到pci

第一部分&#xff1a; CryptMsgUpdate( #endifIN HCRYPTMSG hCryptMsg,IN const BYTE *pbData,IN DWORD cbData,IN BOOL fFinal) {ContentInfo *pci NULL;if ((PHASE_FIRST_FINAL pcmi->dwPhase) &&(0 pcmi->dwMsgType)) {if (0 …

华为交换机S5700设置acl

1.、配置ACL1.1、定义允许的ACL规则[sw1]acl number 3001[sw1-acl-adv-3001]rule permit ip source 192.168.20.0 0.0.0.255 destination 192.168.40.1 0[sw1-acl-adv-3001]rule permit ip source 192.168.30.0 0.0.0.255 destination 192.168.40.1 01.2、定义禁止的ACL规则[sw…

在使用spring ai进行llm处理的rag的时候,选择milvus还是neo4j呢?

在使用spring ai进行llm处理的rag的时候&#xff0c;选择milvus还是neo4j呢&#xff1f; 对于Spring AI中的RAG&#xff08;Retrieval-Augmented Generation&#xff09;应用&#xff0c;选择Milvus还是Neo4j&#xff0c;主要取决于你的数据类型以及RAG流程中对数据检索的侧重点…

计算机视觉与深度学习 | 视觉里程计技术全景解析:从原理到前沿应用

视觉里程计技术全景解析:从原理到前沿应用 一、定义与核心价值 二、技术原理与分类体系 2.1 基本工作流程 2.2 主流技术路线对比 2.3 算法范式演进 三、典型应用场景 3.1 地面移动机器人 3.2 自动驾驶领域 3.3 深空探测 3.4 增强现实 四、核心技术挑战与突破路径 4.1 主要技术…

Wireshark和USRP捕获同一信号波形差异原因

一、波形差异 在前面的博客中我对比绘制了同一信号的Wireshark和USRP两种波形&#xff1a; 可以看出波形差别还是挺大的&#xff0c;尤其是在信号分布间隔方面。 我猜想Wireshark的一条数据包在物理上并不是连续的&#xff1a; 而是分组发送&#xff0c;但在Wireshark中合并在…

Python-GEE遥感云大数据分析、可视化与Satellite Embedding应用

随着航空、航天、近地空间遥感平台的持续发展&#xff0c;遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升&#xff0c;呈现出大数据特征。2025年7月&#xff0c;Google DeepMind发布了革命性的AlphaEarth Foundations模型及Satellite Embedd…

Python常见设计模式2: 结构型模式

文章目录适配器模式桥接模式组合模式外观模式代理模式适配器模式 将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。两种实现方式&#xff1a; 类适配器&#xff1a;使用多继承对象适配器&#xff1a;使用组合…

HDMI2.1 8K验证平台

本文推荐其中一个平台ZCU106HDMI2.1 FMC Card 一、ZCU106主要特性与优势 经过优化&#xff0c;可采用 Zynq Ultrascale MPSoC 快速进行应用原型设计集成型视频编解码器单元支持 H.264/H.265HDMI 视频输入输出PCIe 端点 Gen3x4、USB3、DisplayPort 和 SATADDR4 SODIMM – 64 位…

R语言使用随机森林对数据进行插补

数据插补的目的是为了恢复数据的完整性&#xff0c;以便后续的数据分析和挖掘工作能够顺利进行。插补方法的选择取决于数据的特点和缺失模式。常见的插补方法包括均值插补、回归插补、多重插补等。均值插补简单易行&#xff0c;但可能会改变数据分布&#xff1b;回归插补考虑了…

论文阅读:ICLR 2024 GAIA: A Benchmark for General AI Assistants

https://arxiv.org/pdf/2311.12983 https://www.doubao.com/chat/18484357054754562 GAIA: A Benchmark for General AI Assistants GAIA&#xff1a;通用人工智能助手基准测试 该论文介绍了GAIA&#xff08;General AI Assistants&#xff09;基准测试&#xff0c;这是一…

【Cmake】静态库(编译-链接-引用)相关函数

目录 一.file 1.1.示例一 1.2.示例二 1.2.1.GLOB 1.2.2.GLOB_RECURSE 1.3.示例三 1.3.1.GLOB 1.3.2.GLOB_RECURSE 1.4.file(GLOB)的缺点 二.add_library 示例 1&#xff1a;创建一个简单的静态库 示例 2&#xff1a;创建一个简单的共享库&#xff08;动态库&#x…