首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 連接 MySQL 完整範例:MySqlConnector 最佳實踐與常見坑點

     編輯:關於C語言

前言

官方 `MySql.Data` 驅動歷經多次易手,現已開源但更新緩慢。社區廣泛推薦 **MySqlConnector**(NuGet: `MySqlConnector`),它是全新實現、高效能、支援 .NET Standard 2.0+、完全非同步、修正了許多舊驅動 Bug。本文展示現代連接範例與關鍵設定。

NuGet 安裝

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` 無時區資訊

常見坑點與解決

  1. DataSet 更新失敗:`MySqlDataAdapter.Fill` 後若無主鍵,`Update` 會失敗。解決:查詢包含主鍵欄位,或手動設定 `MissingSchemaAction = MissingSchemaAction.AddWithKey`。
  2. DateTime Kind 遺失:MySQL `DATETIME` 讀出為 `Unspecified`。解決:`reader.GetDateTime(i).SpecifyKind(DateTimeKind.Utc)` 或連線字串 `TreatTinyAsBoolean=false` (無關) —— 最好在 Repository 層統一處理。
  3. 連線未釋放回池:忘記 `Dispose`/`Close`。解決:全程 `await using`。
  4. 大量資料匯入:使用 `MySqlBulkLoader` (LOAD DATA INFILE) 或 `MySqlConnector.BulkCopy`,比逐筆 Insert 快 10-100 倍。

EF Core 整合


// 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 已無歷史包袱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved