一、ADO.NET核心架构与组件
1.1 ADO.NET的定位与优势
- 数据访问统一接口:提供对SQL Server、Oracle、Access等数据库的统一操作方式
- 离线数据模型:通过DataSet实现内存数据库,支持断开式数据操作
- 高性能数据流:DataReader实现只进、只读的快速数据读取
- XML深度集成:原生支持XML格式数据的序列化与转换
1.2 核心组件体系
1.2.1 连接层组件
• SqlConnection:建立与数据库的物理连接
// 连接字符串示例(SQL Server)
string connStr = @"Data Source=.\SQLEXPRESS;
AttachDbFilename=|DataDirectory|\Database.mdf;
Integrated Security=True;
User Instance=True";注意:|DataDirectory|为特殊路径宏,指向项目输出目录的上级目录
• 连接池机制:默认启用,通过Pooling=true/false控制
1.2.2 命令执行组件
• SqlCommand:执行SQL语句/存储过程
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn))
{
// 执行逻辑...
}• 参数化查询(防止SQL注ru):
cmd.CommandText = "INSERT INTO Users(Name) VALUES(@name)";
cmd.Parameters.AddWithValue("@name", "张三");1.2.3 数据访问组件
• SqlDataReader:高性能只读数据流
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader["Name"]);
}
}• SqlDataAdapter:桥接数据库与DataSet
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Products", conn);
DataSet ds = new DataSet();
adapter.Fill(ds, "Products");1.2.4 离线数据容器
• DataSet:内存中的关系型数据集合 • DataTable:数据表的离线操作 • DataRelation:建立表间关系
二、ADO.NET操作全流程
2.1 数据库连接管理
2.1.1 连接字符串最佳实践
• 安全存储:使用配置文件(app.config)存储
<connectionStrings>
<add name="MyDB"
providerName="System.Data.SqlClient"
connectionString="Data Source=.;Initial Catalog=TestDB;Integrated Security=True"/>
</connectionStrings>• 动态获取连接字符串:
string connStr = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;2.1.2 异常处理规范
try
{
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
// 执行操作...
}
}
catch (SqlException ex)
{
// 处理数据库错误(错误号可通过ex.Number获取)
switch (ex.Number)
{
case 18456: MessageBox.Show("登录失败"); break;
case 547: MessageBox.Show("外键约束错误"); break;
default: MessageBox.Show(ex.Message); break;
}
}
catch (Exception ex)
{
// 通用异常处理
}2.2 数据操作实践
2.2.1 增删改操作(ExecuteNonQuery)
string sql = "DELETE FROM Users WHERE Id = @id";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@id", 5);
int rows = cmd.ExecuteNonQuery();
MessageBox.Show($"删除了{rows}条记录");
}2.2.2 查询操作(ExecuteReader)
string sql = "SELECT Id, Name, Age FROM Users WHERE Age > @age";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@age", 18);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
int age = reader.GetInt32(2);
// 处理数据...
}
}
}2.2.3 标量查询(ExecuteScalar)
string sql = "SELECT COUNT(*) FROM Products";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
int count = Convert.ToInt32(cmd.ExecuteScalar());
}2.3 离线数据操作
2.3.1 数据填充与更新
// 填充数据
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Orders", conn);
DataSet ds = new DataSet();
adapter.Fill(ds, "Orders");
// 修改数据
DataTable dt = ds.Tables["Orders"];
dt.Rows[0]["Amount"] = 500;
// 更新回数据库
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.Update(ds, "Orders");2.3.2 数据关系建立
DataRelation rel = new DataRelation("UserOrders",
ds.Tables["Users"].Columns["Id"],
ds.Tables["Orders"].Columns["UserId"]);
ds.Relations.Add(rel);三、WinForm数据绑定
3.1 简单数据绑定
txtName.DataBindings.Add("Text", ds.Tables["Users"], "Name");3.2 复杂数据绑定(DataGridView)
dataGridView1.DataSource = ds.Tables["Products"];
dataGridView1.AutoResizeColumns();3.3 主从表联动
BindingSource masterBS = new BindingSource(ds, "Users");
BindingSource detailBS = new BindingSource(masterBS, "UserOrders");
dataGridView1.DataSource = masterBS;
dataGridView2.DataSource = detailBS;四、常见问题与解决方案
4.1 连接问题
• 错误: "无法打开登录所请求的数据库" • 检查数据库名称拼写 • 验证用户权限 • 确认数据库服务是否启动
• 错误: "超时时间已到" • 增加连接超时设置:Connection Timeout=30 • 检查网络连通性
4.2 数据操作问题
• 问题: 参数化查询无效 • 检查参数名称是否带@符号 • 确保参数顺序与SQL语句一致 • 验证参数数据类型匹配
• 问题: DataSet更新失败 • 确认表已设置主键 • 检查SqlCommandBuilder是否生成正确更新命令
4.3 性能问题
• 现象: 大数据量操作缓慢 • 使用SqlBulkCopy进行批量插入 • 分页加载数据(OFFSET-FETCH) • 避免频繁打开/关闭连接
4.4 内存泄漏
• 原因: 未正确释放资源 • 强制使用using语句管理连接 • 定期调用GC.Collect()(谨慎使用) • 使用内存分析工具(如ANTS Memory Profiler)
五、进阶开发技巧
5.1 DBHelper封装
public static class DBHelper
{
private static string connStr = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddRange(parameters);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}
// 其他方法封装...
}5.2 事务处理
using (SqlTransaction trans = conn.BeginTransaction())
{
try
{
// 执行多个操作...
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
}5.3 异步操作
async Task LoadDataAsync()
{
using (SqlConnection conn = new SqlConnection(connStr))
{
await conn.OpenAsync();
using (SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:05';SELECT * FROM Users", conn))
{
SqlDataReader reader = await cmd.ExecuteReaderAsync();
// 处理数据...
}
}
}六、学习建议与资源
- 官方文档:微软ADO.NET官方指南
- 实战项目:开发库存管理系统(包含CRUD操作)
- 调试技巧: • 使用SQL Server Profiler监控SQL语句 • 在Visual Studio中设置数据库断点
- 安全规范: • 始终使用参数化查询 • 加密存储连接字符串 • 最小化数据库权限
















