官方 `MySql.Data` 驅動歷經多次易手,現已開源但更新緩慢。社區廣泛推薦 **MySqlConnector**(NuGet: `MySqlConnector`),它是全新實現、高效能、支援 .NET Standard 2.0+、完全非同步、修正了許多舊驅動 Bug。本文展示現代連接範例與關鍵設定。
dotnet add package MySqlConnector
Server=192.168.0.13;Port=3306;Database=Flashdata;Uid=root;Pwd=root;
SslMode=Preferred;CharSet=utf8mb4;ConnectionTimeout=30;Pooling=true;MinPoolSize=0;MaxPoolSize=100;
using System;
using System.Data;
using System.Threading.Tasks;
using MySqlConnector;
public class MySqlDemo
{
private readonly string _connStr = "Server=192.168.0.13;Database=Flashdata;Uid=root;Pwd=root;";
public async Task DemoAsync()
{
// 1. 開啟連線
await using var conn = new MySqlConnection(_connStr);
await conn.OpenAsync();
// 2. 執行查詢 - 讀取器模式 (流式,低記憶體)
const string sql = "SELECT Id, UserName, Email, CreatedAt FROM manavatar WHERE IsActive=1 LIMIT 100";
await using var cmd = new MySqlCommand(sql, conn);
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
string email = reader.GetString(2);
DateTime created = reader.GetDateTime(3);
Console.WriteLine($"Id={id}, Name={name}, Email={email}, Created={created:yyyy-MM-dd}");
}
// 3. 執行查詢 - DataTable/DataSet 模式 (小資料集)
var dt = new DataTable();
await using (var da = new MySqlDataAdapter(sql, conn))
{
await da.FillAsync(dt);
}
Console.WriteLine($"DataTable Rows: {dt.Rows.Count}");
// 4. 參數化 Insert/Update
const string insertSql = "INSERT INTO manavatar(UserName, Email, CreatedAt) VALUES(@name, @email, @created)";
await using var insertCmd = new MySqlCommand(insertSql, conn);
insertCmd.Parameters.AddWithValue("@name", "NewUser");
insertCmd.Parameters.AddWithValue("@email", "new@test.com");
insertCmd.Parameters.AddWithValue("@created", DateTime.UtcNow);
int affected = await insertCmd.ExecuteNonQueryAsync();
Console.WriteLine($"Inserted rows: {affected}");
// 5. 交易範例
await using var tx = await conn.BeginTransactionAsync();
try
{
await using var cmd1 = new MySqlCommand("UPDATE manavatar SET Email=@e WHERE Id=1", conn, tx);
cmd1.Parameters.AddWithValue("@e", "tx1@test.com");
await cmd1.ExecuteNonQueryAsync();
await using var cmd2 = new MySqlCommand("UPDATE manavatar SET Email=@e WHERE Id=2", conn, tx);
cmd2.Parameters.AddWithValue("@e", "tx2@test.com");
await cmd2.ExecuteNonQueryAsync();
await tx.CommitAsync();
}
catch
{
await tx.RollbackAsync();
throw;
}
}
}
| 項目 | 建議 | 原因 |
|---|---|---|
| 驅動選擇 | MySqlConnector | 效能優、非同步完整、修正舊驅動 Bug (如 DateTime 解析、連線池洩漏) |
| 字元集 | `CharSet=utf8mb4` | 支援 Emoji、完整 Unicode,避免 `utf8` (實為 utf8mb3) 截斷 |
| SSL | `SslMode=Preferred` 或 `Required` | 生產環境強制加密,開發環境可用 `None` |
| 連線池 | `Pooling=true;MinPoolSize=0;MaxPoolSize=100` | 預設開啟,高併發調大 MaxPoolSize |
| 命令逾時 | `DefaultCommandTimeout=60` (連線字串或命令屬性) | 防止長查詢卡死執行緒 |
| 資源釋放 | `await using` / `using` | 確保連線歸還池、讀取器關閉 |
| 參數化 | **永遠使用參數** | 防 SQL 注入、計畫快取重用、型別安全 |
| 日期時間 | 儲存 UTC (`DateTime.UtcNow`),讀取後指定 `DateTimeKind.Utc` | 避免時區混淆,MySQL `DATETIME` 無時區資訊 |
// Program.cs / Startup.cs
services.AddDbContext(options =>
options.UseMySql(
Configuration.GetConnectionString("MySQL"),
ServerVersion.AutoDetect(Configuration.GetConnectionString("MySQL")) // 自動偵測版本
).EnableSensitiveDataLogging() // 僅開發環境
);
NuGet: `MySql.EntityFrameworkCore` (官方) 或 `Pomelo.EntityFrameworkCore.MySql` (社區熱門,功能更全)。
**棄用 `MySql.Data`,改用 `MySqlConnector`**。採用 `async/await` 全非同步流程、參數化查詢、正確字元集與連線池設定,即可獲得穩定、高效能的 MySQL 存取體驗。配合 EF Core Provider,現代 .NET 專案操作 MySQL 已無歷史包袱。