
时间2026年8月第3周标签#CSharp #ADO.NET #MySQL #数据库 #学习总结前言本周我们告别了基础的语法学习正式开启了 C# 数据访问的大门。如果说之前的代码是“单机游戏”那么现在的代码就是“联网游戏”。我们从如何连接数据库Connection到如何执行 SQL 命令Command再到如何处理事务和封装工具类每一天都在构建更稳固的编程思想。以下是本周的学习复盘。ADO.NET 概述程序与数据的桥梁ADO.NET 是微软在 .NET 框架中提供的一组用于访问数据库的组件。它就像一座桥梁连接着我们的 C# 程序和 MySQL、SQL Server 等数据源。核心优势ADO.NET 最大的特点在于支持“断开式”数据访问。这意味着我们可以在与数据库断开连接的情况下在内存中对数据进行修改然后再将更新情况返回给数据库。这种方式极大地减少了数据库连接的占用时间提升了服务器的性能。连接 MySQL本周我们实践了 C# 连接 MySQL 数据库。关键步骤是引入MySql.Data.dll驱动文件并在项目中添加引用然后使用using MySql.Data.MySqlClient;命名空间。Connection 对象建立数据传输通道Connection对象是 ADO.NET 的起点它负责在应用程序和数据库之间建立一条数据传输通道。连接字符串创建Connection对象前需要定义一个连接字符串它包含了服务器地址server、用户名uid、密码pwd、数据库名database等关键信息。核心操作创建对象MySqlConnection con new MySqlConnection(sqlstr);打开连接con.Open();关闭连接con.Close();最佳实践为了节省系统资源数据库连接应遵循“用时打开用完即关”的原则。我们通常将Open()和Close()方法放在try-catch-finally结构中确保无论是否发生异常连接都能被正确关闭。连接状态通过State属性可以判断连接的当前状态如Open打开、Closed关闭等。Command 对象执行 SQL 命令Command对象用于向数据库发送 SQL 命令执行增、删、改、查等操作。核心属性CommandText获取或设置要对数据库执行的 SQL 语句。Connection获取或设置该命令使用的Connection对象。三大核心方法ExecuteNonQuery()执行不返回结果集的 SQL 语句如INSERT、UPDATE、DELETE。它返回一个int值表示受影响的行数。ExecuteScalar()执行查询并返回结果集中第一行第一列的值。常用于执行COUNT(*)这类聚合函数查询。ExecuteReader()执行查询命令并返回一个DataReader对象用于读取数据。DataReader 对象只进只读的数据流DataReader对象提供了一个高效、只进只读的数据读取器用于从数据库中逐行读取数据。核心特点只进只读数据只能从前往后读取不能修改。连接状态在读取数据的过程中必须保持与数据库的连接处于打开状态。高性能因为它不会将所有数据一次性加载到内存中而是像水流一样逐行读取所以内存占用小速度快。使用流程通过Command对象的ExecuteReader()方法获取DataReader对象。使用while (reader.Read())循环逐行读取数据。通过reader[列名]或reader[索引]获取指定列的值。读取完毕后调用reader.Close()关闭读取器。DataSet 与 DataAdapter断开式数据访问DataSet是 ADO.NET 的核心概念可以把它看作是“内存中的数据库”。DataSet一个独立于数据源的数据集合。即使断开数据库连接DataSet依然可用。它内部使用 XML 描述数据可以容纳多个DataTable数据表以及表之间的关系。DataAdapterDataAdapter是DataSet和数据源之间的桥梁。它负责使用Fill()方法将数据从数据库填充到DataSet中或者使用Update()方法将DataSet中的更改更新回数据库。两种访问模式对比连接式访问CommandDataReader适用于快速读取大量数据但需要一直保持连接。断开式访问DataAdapterDataSet适用于需要对数据进行复杂操作、缓存或在多层应用中传递数据的场景。事务处理保证数据的一致性事务是将多个数据库操作组合成一个不可分割的逻辑单元。这些操作要么全部成功要么全部失败以此来保证数据的一致性和完整性。核心流程通过Connection对象的BeginTransaction()方法开启一个事务。将Command对象的Transaction属性设置为当前事务。执行多个 SQL 命令。如果所有操作都成功调用transaction.Commit()提交事务。如果任何一个操作失败在catch块中调用transaction.Rollback()回滚事务撤销所有已执行的操作。应用场景银行转账是事务的经典案例。从 A 账户扣钱和向 B 账户加钱必须作为一个事务来执行否则就会出现数据不一致的问题。DBHelper 工具类代码的封装与复用为了提高代码的可读性和可维护性我们学习了如何封装一个通用的DBHelper类。封装思想将数据库连接、打开、关闭以及执行命令的重复性代码提取到一个独立的类中。核心方法DBHelper类通常包含ExecuteNonQuery、ExecuteScalar、ExecuteReader等通用方法。优势在业务代码中我们只需要实例化DBHelper对象并调用其方法传入 SQL 语句即可无需关心底层的连接细节。这大大简化了数据访问层的代码是良好的编程实践。完整的 C# DBHelper 工具类示例下面是一个完整的、可运行的 C# DBHelper 工具类示例它包含了连接字符串配置、通用的 ExecuteNonQuery、ExecuteScalar、ExecuteReader 方法并演示了如何在业务代码中调用它。using System; using System.Data; using MySql.Data.MySqlClient; namespace MyProject.DataAccess { /// summary /// 数据库操作工具类 /// /summary public class DBHelper { // 连接字符串通常从配置文件读取此处为示例 private static readonly string connectionString serverlocalhost;port3306;databasemydb;uidroot;pwd123456;charsetutf8mb4;; /// summary /// 执行增、删、改操作返回受影响的行数 /// /summary /// param namesqlSQL语句/param /// param nameparameters参数数组可选/param /// returns受影响的行数/returns public static int ExecuteNonQuery(string sql, params MySqlParameter[] parameters) { using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); using (MySqlCommand cmd new MySqlCommand(sql, conn)) { if (parameters ! null parameters.Length 0) { cmd.Parameters.AddRange(parameters); } return cmd.ExecuteNonQuery(); } } } /// summary /// 执行查询返回结果集中第一行第一列的值 /// /summary /// param namesqlSQL语句/param /// param nameparameters参数数组可选/param /// returns第一行第一列的值object类型/returns public static object ExecuteScalar(string sql, params MySqlParameter[] parameters) { using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); using (MySqlCommand cmd new MySqlCommand(sql, conn)) { if (parameters ! null parameters.Length 0) { cmd.Parameters.AddRange(parameters); } return cmd.ExecuteScalar(); } } } /// summary /// 执行查询返回一个 DataReader 对象 /// /summary /// param namesqlSQL语句/param /// param nameparameters参数数组可选/param /// returnsMySqlDataReader 对象/returns public static MySqlDataReader ExecuteReader(string sql, params MySqlParameter[] parameters) { MySqlConnection conn new MySqlConnection(connectionString); MySqlCommand cmd new MySqlCommand(sql, conn); if (parameters ! null parameters.Length 0) { cmd.Parameters.AddRange(parameters); } conn.Open(); // CommandBehavior.CloseConnection 确保关闭 Reader 时自动关闭连接 return cmd.ExecuteReader(CommandBehavior.CloseConnection); } /// summary /// 执行查询返回一个 DataTable /// /summary /// param namesqlSQL语句/param /// param nameparameters参数数组可选/param /// returnsDataTable 对象/returns public static DataTable ExecuteDataTable(string sql, params MySqlParameter[] parameters) { using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); using (MySqlCommand cmd new MySqlCommand(sql, conn)) { if (parameters ! null parameters.Length 0) { cmd.Parameters.AddRange(parameters); } using (MySqlDataAdapter adapter new MySqlDataAdapter(cmd)) { DataTable dt new DataTable(); adapter.Fill(dt); return dt; } } } } } }在业务代码中调用 DBHelper以下是如何在业务代码中使用上述 DBHelper 类的示例using System; using MySql.Data.MySqlClient; using MyProject.DataAccess; // 假设 DBHelper 在此命名空间 class Program { static void Main(string[] args) { // 1. 插入数据示例 string insertSql INSERT INTO Users (Name, Age) VALUES (name, age); MySqlParameter[] insertParams { new MySqlParameter(name, 张三), new MySqlParameter(age, 25) }; int rowsAffected DBHelper.ExecuteNonQuery(insertSql, insertParams); Console.WriteLine($插入成功影响行数{rowsAffected}); // 2. 查询单个值示例如获取用户总数 string countSql SELECT COUNT(*) FROM Users; object countResult DBHelper.ExecuteScalar(countSql); int userCount Convert.ToInt32(countResult); Console.WriteLine($用户总数{userCount}); // 3. 查询多行数据示例使用 DataReader string querySql SELECT Id, Name, Age FROM Users WHERE Age age; MySqlParameter queryParam new MySqlParameter(age, 20); using (var reader DBHelper.ExecuteReader(querySql, queryParam)) { while (reader.Read()) { Console.WriteLine($ID: {reader[Id]}, 姓名: {reader[Name]}, 年龄: {reader[Age]}); } } // 4. 查询数据到 DataTable 示例 string dtSql SELECT * FROM Users; DataTable userTable DBHelper.ExecuteDataTable(dtSql); foreach (DataRow row in userTable.Rows) { Console.WriteLine($ID: {row[Id]}, 姓名: {row[Name]}); } // 5. 更新数据示例 string updateSql UPDATE Users SET Age newAge WHERE Name name; MySqlParameter[] updateParams { new MySqlParameter(newAge, 30), new MySqlParameter(name, 张三) }; int updatedRows DBHelper.ExecuteNonQuery(updateSql, updateParams); Console.WriteLine($更新成功影响行数{updatedRows}); } }关键说明连接字符串示例中的连接字符串是硬编码的实际项目中应将其放在App.config或appsettings.json配置文件中通过ConfigurationManager或IConfiguration动态读取。参数化查询所有方法都支持参数化查询MySqlParameter这能有效防止 SQL 注入攻击。资源管理使用了using语句确保MySqlConnection、MySqlCommand等对象在使用后及时释放。扩展性你可以根据需要为DBHelper类添加事务支持、异步方法ExecuteNonQueryAsync等或更复杂的查询方法。总结与展望本周的学习是从“编写代码”到“操作数据”的思维转变。Connection建立了与数据库的桥梁。Command执行了对数据的操作。DataReader和DataSet提供了两种不同的数据读取模式。事务保证了数据操作的原子性和一致性。DBHelper则体现了代码封装和复用的重要性。接下来我们需要通过一个完整的项目来串联这些知识点实践从界面设计到数据库操作的完整开发流程。下周继续加油