C#操作MySQL数据库在项目开发中非常常见,无论是WinForm桌面程序、Web服务还是后台任务,都绕不开和数据库打交道。要在C#里使用MySQL,核心是借助MySQL官方提供的.NET驱动程序,通过它建立连接、发送SQL语句并处理返回结果。这篇文章会从驱动安装开始,一步步演示完整的操作流程,包括连接、查询、增删改、参数化查询和事务处理。

一、安装MySQL的.NET驱动包
MySQL官方为.NET平台提供了两个主流驱动:一个是MySql.Data,由Oracle官方维护,功能完整且文档齐全;另一个是MySqlConnector,属于社区开发的第三方驱动,完全异步支持更好,性能在高并发场景下表现突出。对大多数初学者和常规项目来说,MySql.Data已经够用,本文也以它为例。
安装方式推荐用NuGet包管理器。在Visual Studio中右键项目,选择管理NuGet程序包,搜索MySql.Data并安装即可。也可以用命令行方式:
Install-Package MySql.Data // 或者使用.NET CLI dotnet add package MySql.Data
安装完成后,在代码文件顶部引入命名空间using MySql.Data.MySqlClient;,后面所有和MySQL相关的类都在这个命名空间下。需要注意的是,如果你的项目是.NET Core 3.1以上或.NET 5/6/7/8,直接安装最新版即可;如果是老的项目如.NET Framework 4.5,可能需要安装兼容版本,否则会报程序集加载失败的问题。
二、建立数据库连接并执行基本SQL语句
连接MySQL的第一步是构造连接字符串。连接字符串里包含服务器地址、端口、数据库名、用户名和密码这几个核心参数,格式如下:
string connStr = "server=127.0.0.1;port=3306;database=testdb;uid=root;pwd=123456;charset=utf8mb4;";
using (MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
Console.WriteLine("连接成功,状态:" + conn.State);
// 执行一条查询语句
string sql = "SELECT id, name, age FROM users";
using (MySqlCommand cmd = new MySqlCommand(sql, conn))
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"ID:{reader["id"]}, 姓名:{reader["name"]}, 年龄:{reader["age"]}");
}
}
}这段代码有几个关键点。第一,MySqlConnection和MySqlCommand都实现了IDisposable接口,用using语句包裹可以确保资源及时释放,避免连接泄漏。第二,查询用ExecuteReader返回一个只进只读的游标,适合数据量大、需要逐行处理的场景;如果只取单个值(比如查询总数),用ExecuteScalar更方便;执行INSERT、UPDATE、DELETE这类不返回结果集的语句,则用ExecuteNonQuery,它会返回受影响的行数。
连接字符串里的charset=utf8mb4建议始终加上,否则插入中文可能乱码。如果遇到连接超时,可以加上Connection Timeout=30;连接池默认是开启的,重复创建连接对象的开销并不大,因为底层会复用物理连接。
三、参数化查询防止SQL注入
拼接SQL字符串是最危险也最常见的错误写法。比如"SELECT * FROM users WHERE name='" + name + "'",一旦用户输入中包含单引号,轻则查询报错,重则整个数据库被拖库。正确做法是使用参数化查询:
string sql = "INSERT INTO users(name, age) VALUES(@name, @age)";
using (MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@name", "张三");
cmd.Parameters.AddWithValue("@age", 25);
int rows = cmd.ExecuteNonQuery();
Console.WriteLine($"成功插入 {rows} 行");
}
}参数化查询的原理是SQL语句结构和数据分离,参数值不会被当成SQL指令解析,从根源上杜绝了注入攻击。注意MySQL的参数占位符用@符号加参数名,这一点和SQL Server一致,但与Oracle的冒号前缀不同。另外AddWithValue会自动推断类型,某些特殊场景下显式用cmd.Parameters.Add("@age", MySqlDbType.Int32).Value = 25;指定类型更稳妥,能避免隐式类型转换导致的索引失效。
四、用DataAdapter填充DataTable和处理事务
如果希望把查询结果一次性拿到内存里离线操作,MySqlDataAdapter配合DataTable是常用组合,尤其在绑定DataGridView这类控件时特别方便:
DataTable dt = new DataTable();
using (MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM users", connStr))
{
da.Fill(dt);
}
Console.WriteLine($"共查询到 {dt.Rows.Count} 条数据");Fill方法内部会自动打开和关闭连接,不需要手动调用Open。这种离线方式适合数据量不大的报表、配置加载场景;数据量很大时还是应该用DataReader流式读取,避免内存被撑爆。
涉及多条SQL必须同时成功或同时失败的业务,比如转账操作,就要用到事务。事务能保证原子性,任何一步失败都可以整体回滚:
using (MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
MySqlTransaction trans = conn.BeginTransaction();
try
{
new MySqlCommand("UPDATE account SET money=money-100 WHERE id=1", conn, trans).ExecuteNonQuery();
new MySqlCommand("UPDATE account SET money=money+100 WHERE id=2", conn, trans).ExecuteNonQuery();
trans.Commit();
Console.WriteLine("转账成功");
}
catch (Exception ex)
{
trans.Rollback();
Console.WriteLine("转账失败已回滚:" + ex.Message);
}
}使用事务时务必保证所有命令绑定同一个事务对象,并且提交或回滚后连接要正常释放。实际项目中还应记录异常日志,给表添加合适的索引来提升查询性能。掌握这些基础操作后,再接触Dapper、EF Core这类ORM框架会轻松很多,因为它们底层调用的正是今天讲的这些ADO.NET对象。
C#操作MySQLMySQL驱动MySqlConnection修改时间:2026-09-14 00:20:46