一、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();
            // 处理数据...
        }
    }
}


六、学习建议与资源

  1. 官方文档微软ADO.NET官方指南
  2. 实战项目:开发库存管理系统(包含CRUD操作)
  3. 调试技巧: • 使用SQL Server Profiler监控SQL语句 • 在Visual Studio中设置数据库断点
  4. 安全规范: • 始终使用参数化查询 • 加密存储连接字符串 • 最小化数据库权限