-
C#操作ADO.NET连接SQL Server——基础查询
第一部分:C#基础入门
ADO.NET连接SQL Server——基础查询
实例介绍
ADO.NET是.NET框架中用于操作关系型数据库的底层API,它提供了直接与数据库交互的能力,相比ORM框架(如EF Core)更灵活、性能更高,适合对数据库操作有精细控制的场景(如批量数据处理、性能敏感业务)。
本节通过“学生信息查询”场景,带你掌握ADO.NET连接SQL Server的核vb.net教程C#教程python教程SQL教程access 2010教程心流程:连接数据库→执行查询→读取结果→释放资源,同时规避SQL注入等常见风险。
需求分析
设计一个学生信息查询工具,核心需求:
1.连接SQL Server:通过连接字符串建立与数据库的连接;
2.执行查询:执行SELECT语句获取学生表数据;
3.安全读取:避免SQL注入,正确读取不同类型的字段值;
4.资源管理:自动释放数据库连接、命令等资源;
5.异常处理:捕获数据库操作中的常见异常(如连接失败、查询错误)。
代码实现
前置条件:
安装SQL Server(或LocalDB);
创建数据库SchoolDB,并新建Students表:
sql
CREATE TABLE Students (
Id INT PRIMARY KEY IDENTITY(1,1),
Name NVARCHAR(50) NOT NULL,
Age INT NOT NULL,
Major NVARCHAR(50) NOT NULL
);
-- 插入测试数据
INSERT INTO Students (Name, Age, Major) VALUES
('张三', 20, '计算机科学'),
('李四', 21, '电子工程'),
('王五', 19, '软件工程');
csharp
using System;
using System.Data.SqlClient; // ADO.NET SQL Server核心命名空间
class Program {
// 连接字符串:替换为你的SQL Server实例信息
private static readonly string ConnectionString = @"
Data Source=(localdb)MSSQLLocalDB; -- 本地DB实例
Initial Catalog=SchoolDB; -- 数据库名
Integrated Security=True; -- Windows身份验证
Connect Timeout=30; -- 连接超时时间
";
static void Main() {
QueryStudents();
}
/// <summary>
/// 查询所有学生信息
/// </summary>
static void QueryStudents() {
// 1. 使用using语句自动释放资源(IDisposable接口)
using (SqlConnection connection = new SqlConnection(ConnectionString)) {
try {
// 2. 打开数据库连接
connection.Open();
Console.WriteLine("数据库连接成功!");
// 3. 定义查询语句(参数化查询,避免SQL注入)
string query = "SELECT Id, Name, Age, Major FROM Students WHERE Age > @MinAge";
using (SqlCommand command = new SqlCommand(query, connection)) {
// 添加参数(防止SQL注入)
command.Parameters.AddWithValue("@MinAge", 19);
// 4. 执行查询,获取数据阅读器
using (SqlDataReader reader = command.ExecuteReader()) {
Console.WriteLine("
学生信息列表:");
Console.WriteLine("---------------------------");
Console.WriteLine("ID | 姓名 | 年龄 | 专业");
Console.WriteLine("---------------------------");
// 5. 循环读取数据(Read()返回true表示有下一行)
while (reader.Read()) {
// 安全读取字段值:通过列名获取索引,再读取对应类型
int id = reader.GetInt32(reader.GetOrdinal("Id"));
string name = reader.GetString(reader.GetOrdinal("Name"));
int age = reader.GetInt32(reader.GetOrdinal("Age"));
string major = reader.GetString(reader.GetOrdinal("Major"));
Console.WriteLine($"{id} | {name} | {age} | {major}");
}
}
}
} catch (SqlException ex) {
Console.WriteLine($"数据库错误:{ex.Message}");
} catch (Exception ex) {
Console.WriteLine($"系统错误:{ex.Message}");
}
// using语句自动关闭连接(即使发生异常)
}
}
}
逐行讲解
-
连接字符串配置
Data Source:指定SQL Server实例(如(localdb)MSSQLLocalDB是Windows自带的本地实例);
Initial Catalog:目标数据库名;
Integrated Security:启用Windows身份验证(无需输入用户名密码);
Connect Timeout:连接超时时间(单位:秒)。 -
using语句的作用
using (SqlConnection connection = ...):SqlConnection实现了IDisposable接口,using语句会在代码块结束后自动调用Dispose()方法,释放连接资源(避免手动关闭连接的繁琐);
同理,SqlCommand和SqlDataReader也需用using包裹,确保资源及时释放。 -
数据库连接与查询
connection.Open():建立与数据库的物理连接(连接池会复用已有连接,提升性能);
SqlCommand:封装SQL语句和连接信息,CommandText是查询语句,Connection指定关联的连接;
参数化查询:command.Parameters.AddWithValue("@MinAge",19)通过参数替换SQL中的变量,彻底防止SQL注入(对比字符串拼接:"WHERE Age > "+minAge易被注入攻击)。 -
数据读取
ExecuteReader():执行查询并返回SqlDataReader(仅向前、只读的数据流,性能高);
reader.Read():移动到下一行数据,返回true表示存在数据;
安全读取字段:reader.GetOrdinal("Name")获取列名对应的索引,再用GetString()/GetInt32()读取对应类型的值(避免列顺序变化导致的错误)。 -
异常处理
SqlException:捕获数据库特有异常(如连接失败、SQL语法错误);
通用Exception:捕获其他系统异常(如网络问题);
即使发生异常,using语句仍会自动关闭连接,避免资源泄漏。
基础知识拓展 - ADO.NET核心组件
| 组件 | 作用 |
|---|---|
| SqlConnection | 建立与SQL Server的连接 |
| SqlCommand | 执行SQL语句或存储过程 |
| SqlDataReader | 向前、只读的数据流,适合批量读取大数量数据(性能最优) |
| SqlDataAdapter | 填充DataTable/DataSet(支持离线操作,适合小批量数据) |
| DataSet | 内存中的数据库副本,包含多个DataTable,支持关系和约束 |
-
连接池原理
连接池:ADO.NET自动维护一个连接池,当调用connection.Open()时,优先从池内获取空闲连接;调用connection.Close()时,连接不会真正关闭,而是返回池内等待复用;
配置连接池:通过连接字符串参数调整:
Max Pool Size:最大连接数(默认100);
Min Pool Size:最小空闲连接数(默认0);
Pooling:是否启用连接池(默认true)。 -
SQL注入防护
风险示例:字符串拼接查询"SELECT * FROM Students WHERE Name = '"+name+"'",若name为' OR '1'='1,则SQL变为SELECT * FROM Students WHERE Name='' OR '1'='1',返回所有数据;
解决方案:始终使用参数化查询(SqlCommand.Parameters),ADO.NET会自动对参数进行转义,防止注入。 - DataReader vs DataTable
| 特性 | SqlDataReader | DataTable(通过SqlDataAdapter填充) |
|---|---|---|
| 数据读取方式 | 向前、只读 | 随机访问、可修改 |
| 内存占用 | 低(逐行读取) | 高(一次性加载所有数据) |
| 性能 | 高(适合大数量数据) | 低(适合小批量数据) |
| 离线支持 | 不支持(需保持连接) | 支持(离线操作) |
-
命令类型(CommandType)
Text:执行SQL文本语句(默认);
StoredProcedure:执行存储过程(command.CommandText = "GetStudents");
TableDirect:直接读取整个表(command.CommandText = "Students",仅适用于OLE DB)。
总结
ADO.NET是C#操作SQL Server的基础工具,掌握它能让你深入理解数据库交互的底层逻辑,即使在ORM框架盛行的今天,ADO.NET依然是排查数据库问题、优化性能的关键技能。本节通过学生信息查询实例,带你掌握了连接数据库、执行参数化查询、读取数据、资源管理的完整流程,同时拓展了连接池、SQL注入防护等核心知识点。
在实际开发中,建议优先使用参数化查询,避免SQL注入;用using语句管理资源,减少内存泄漏风险;根据数据规模选择SqlDataReader(大数量)或DataTable(小批量)。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49434.html
最新更新
参数化查询——C#编写防止SQL注入攻击
C#操作ADO.NET连接SQL Server——基础查询
模式匹配——C#编写复杂对象类型判断
模式匹配——C#编写复杂对象类型判断
元组与记录——C#编写简化数据传输对象
动态类型——C#编写COM组件交互
表达式树——C#测试动态查询构建器
LINQ高级查询——C#进行复杂数据分组与聚
异步IO操作——C#编写关于大文件多线程下
异步编程基础——C#开发Task异步方法设计
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比










