Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 9.1 ADO.NET基础

9.1 ADO.NET基础

1. ADO.NET概述

ADO.NET是.NET Framework中用于数据访问的核心组件,提供了一组类库用于连接数据库、执行命令和检索结果。它是现代C#应用程序与数据库交互的标准方式。

关键特性:

  • 断开式数据访问模型
  • 与XML紧密集成
  • 高性能数据访问
  • 支持多种数据源

2. ADO.NET核心组件

2.1 数据提供程序(Data Providers)

提供程序名称对应数据库核心类前缀
SqlClientSQL ServerSql
OleDbOLE DB兼容OleDb
OdbcODBC兼容Odbc
OracleClientOracleOracle

2.2 核心类

  • Connection:建立与数据源的连接
  • Command:执行SQL命令或存储过程
  • DataReader:提供只进、只读的数据流
  • DataAdapter:在数据源和DataSet之间架桥
  • DataSet:内存中的数据库表示
  • DataTable:内存中的表表示

3. 基本数据访问流程

3.1 连接数据库

using System.Data.SqlClient;

string connectionString = "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // 执行数据库操作
}

3.2 执行查询

string sql = "SELECT * FROM Customers WHERE Country = @Country";
using (SqlCommand command = new SqlCommand(sql, connection))
{
    command.Parameters.AddWithValue("@Country", "Germany");
    
    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine($"ID: {reader["CustomerID"]}, Name: {reader["CompanyName"]}");
        }
    }
}

3.3 执行非查询操作

string insertSql = "INSERT INTO Products (ProductName, UnitPrice) VALUES (@Name, @Price)";
using (SqlCommand command = new SqlCommand(insertSql, connection))
{
    command.Parameters.AddWithValue("@Name", "New Product");
    command.Parameters.AddWithValue("@Price", 19.99);
    
    int rowsAffected = command.ExecuteNonQuery();
    Console.WriteLine($"{rowsAffected} row(s) inserted.");
}

4. 参数化查询

为什么使用参数化查询?

  • 防止SQL注入攻击
  • 提高性能(查询计划重用)
  • 处理特殊字符更安全

参数化查询示例

string sql = "UPDATE Employees SET Salary = @Salary WHERE EmployeeID = @ID";
using (SqlCommand cmd = new SqlCommand(sql, connection))
{
    cmd.Parameters.Add("@Salary", SqlDbType.Decimal).Value = 55000.00m;
    cmd.Parameters.Add("@ID", SqlDbType.Int).Value = 5;
    
    cmd.ExecuteNonQuery();
}

5. 事务处理

基本事务示例

using (SqlTransaction transaction = connection.BeginTransaction())
{
    try
    {
        // 执行多个命令
        command1.Transaction = transaction;
        command1.ExecuteNonQuery();
        
        command2.Transaction = transaction;
        command2.ExecuteNonQuery();
        
        // 提交事务
        transaction.Commit();
    }
    catch
    {
        // 回滚事务
        transaction.Rollback();
        throw;
    }
}

6. 断开式数据访问(DataSet/DataTable)

使用DataAdapter填充DataSet

string sql = "SELECT * FROM Products; SELECT * FROM Categories";
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, connection))
{
    DataSet ds = new DataSet();
    adapter.Fill(ds);
    
    DataTable products = ds.Tables[0];
    DataTable categories = ds.Tables[1];
    
    // 处理数据...
}

更新数据源

// 修改DataTable中的数据后...
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Products", connection))
{
    SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
    adapter.Update(ds.Tables[0]);  // 将更改同步回数据库
}

7. 最佳实践

  1. 连接管理:

    • 使用using语句确保连接及时关闭
    • 避免频繁打开/关闭连接,考虑连接池
  2. 错误处理:

    • 捕获特定异常(SqlException)
    • 实现重试逻辑
  3. 性能优化:

    • 使用存储过程代替动态SQL
    • 批量操作代替单行操作
    • 合理使用连接池
  4. 安全考虑:

    • 永远不要拼接SQL字符串
    • 最小权限原则配置数据库账户
    • 加密敏感连接字符串信息

8. 常见问题与解决方案

问题1:连接字符串泄露敏感信息

  • 解决方案:使用配置管理器或Azure Key Vault存储连接字符串

问题2:连接泄漏

  • 解决方案:确保所有连接对象都在using块中创建

问题3:长时间运行的查询

  • 解决方案:设置CommandTimeout属性

问题4:并发冲突

  • 解决方案:实现乐观并发控制

9. 现代替代方案

虽然ADO.NET仍然是.NET数据访问的基础,但现代开发中更多使用:

  • Entity Framework Core(ORM框架)
  • Dapper(轻量级ORM)
  • 各种NoSQL客户端库

然而,理解ADO.NET基础对于处理复杂场景和性能关键型应用仍然至关重要。

Last Updated:: 5/3/25, 11:34 PM