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

C# 讀取 MySQL 多結果集:使用 MySqlDataAdapter 與 MySqlDataReader 實作

     編輯:Java 相關知識

背景

MySQL 預存程序或批次 SQL 可一次返回多個結果集。C# 中需結合 MySqlDataReader 的 NextResult() 與 MySqlDataAdapter.FillAsync() 依序讀取每個結果集並填入 DataTable。

核心類別與方法

  • MySqlDataReader:NextResult() 移動到下一個結果集,返回 true 表示存在。
  • MySqlDataAdapter:FillAsync(DataTable, IDataReader) 將當前結果集資料填入 DataTable。

完整實作程式碼

using System;
using System.Collections.Generic;
using System.Data;
using System.Threading;
using MySql.Data.MySqlClient;

public struct SqlParam {
    public string Name;
    public object Value;
    public SqlParam(string n, object v) { Name = n; Value = v; }
}

public class MySqlHelper {
    private readonly MySqlConnection _conn;

    public MySqlHelper(string connStr) { _conn = new MySqlConnection(connStr); }

    /// 
    /// 執行預存程序或批次 SQL,返回多個 DataTable 列表
    /// 
    public List<DataTable> ExecuteMultipleResults(string spName, List<SqlParam> parameters) {
        var tables = new List<DataTable>();
        using (var cmd = new MySqlCommand(spName, _conn)) {
            cmd.CommandType = CommandType.StoredProcedure;
            foreach (var p in parameters)
                cmd.Parameters.AddWithValue(p.Name, p.Value);

            _conn.Open();
            using (var reader = cmd.ExecuteReader()) {
                var adapter = new MySqlDataAdapter();
                var cts = new CancellationTokenSource(); // 可選:支援取消
                bool hasMore = true;
                while (hasMore) {
                    var dt = new DataTable();
                    // 同步等待填充完成;生產環境建議改用 await FillAsync
                    adapter.FillAsync(dt, reader).Wait(cts.Token);
                    tables.Add(dt);
                    hasMore = reader.NextResult(); // 移至下一結果集
                }
            }
        }
        return tables;
    }
}

使用範例

var helper = new MySqlHelper("Server=localhost;Database=test;Uid=root;Pwd=123456;");
var pars = new List<SqlParam> { new SqlParam("startPage", 0), new SqlParam("pageSize", 10) };
List<DataTable> results = helper.ExecuteMultipleResults("sp_get_posters", pars);

// results[0] -> SELECT COUNT(*) FROM poster;
// results[1] -> SELECT PosterID, PostTime, Title ... LIMIT ...
Console.WriteLine("總筆數:" + results[0].Rows[0][0]);
foreach (DataRow row in results[1].Rows)
    Console.WriteLine($"{row["PosterID"]}\t{row["PostTime"]}\t{row["Title"]}");

關鍵注意事項

  1. 連線物件:MySqlConnection 需預先建立並開啟,讀取完畢自動關閉(using 區塊)。
  2. 非同步最佳化:生產環境請改用 await adapter.FillAsync(dt, reader, cancellationToken) 避免阻塞執行緒。
  3. 參數結構:範例使用簡易 SqlParam 結構體,實際專案可直接用 MySqlParameter 集合。
  4. 序列化陷阱:若 DataTable 需跨序列化邊界,注意 DataTable.RemotingFormat = SerializationFormat.Binary 可減小體積。

原理解析

MySqlDataAdapter.FillAsync 內部透過反射呼叫 DataTable.Load(IDataReader),而 MySqlDataReader 實作 IDataReader,NextResult() 推進內部結果集游標。兩者配合即可流式處理多結果集,記憶體佔用僅與單一結果集大小成正比。

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