You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ODP.NET Core将Oracle查询结果转为List、DataSet或JSON?

解决方案

无限循环原因说明

  • reader.OfType<object>()触发无限循环,是因为DbDataReader的枚举器逻辑问题:它的GetEnumerator()默认遍历行,但OfType<object>()会错误地重复读取行,导致无法终止遍历。
  • OracleDataAdapter.Fill(data)的“无限循环”大概率是调试器假死:当查询结果集过大时,调试器展开DataSet会递归加载关联对象,造成类似无限循环的卡顿,并非代码本身存在循环。可以通过添加rownum <= 10限制查询行数验证。

最优转换方式

1. 转动态对象列表(无需实体类,灵活高效)

手动遍历Reader,用ExpandoObject生成动态对象,无需提前定义实体类:

var result = new List<object>();
using (var connection = new OracleConnection(CONNECTION_STRING))
{
    connection.Open();
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "select * from <table>";
        using (var reader = cmd.ExecuteReader())
        {
            // 获取所有列名
            var columnNames = Enumerable.Range(0, reader.FieldCount)
                                        .Select(reader.GetName)
                                        .ToList();
            while (reader.Read())
            {
                var row = new ExpandoObject() as IDictionary<string, object>;
                foreach (var col in columnNames)
                {
                    // 处理DBNull值,转为null
                    row[col] = reader[col] == DBNull.Value ? null : reader[col];
                }
                result.Add(row);
            }
        }
    }
}
return result;

这种方式兼顾灵活性和可读性,遍历一次即可完成转换,适合快速开发场景。

2. 转DataSet/DataTable(传统ADO.NET兼容方案)

如果需要兼容传统DataSet场景,优化资源管理代码即可:

using (var connection = new OracleConnection(CONNECTION_STRING))
{
    var dataSet = new DataSet();
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "select * from <table>";
        // OracleDataAdapter会自动管理连接的打开/关闭,无需手动Open
        using (var adapter = new OracleDataAdapter(cmd))
        {
            adapter.Fill(dataSet);
        }
    }
    return dataSet;
}

注意用using块自动释放连接和资源,无需手动调用Close()——using结束时会自动执行Dispose(),包含连接关闭逻辑。

3. 直接转JSON(API场景最优)

如果最终输出是JSON,可直接从Reader转成JSON,无需中间集合:

using (var connection = new OracleConnection(CONNECTION_STRING))
{
    connection.Open();
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "select * from <table>";
        using (var reader = cmd.ExecuteReader())
        {
            var columnNames = Enumerable.Range(0, reader.FieldCount)
                                        .Select(reader.GetName)
                                        .ToList();
            var rows = new List<Dictionary<string, object>>();
            while (reader.Read())
            {
                // 每行转成字典
                var rowDict = columnNames.ToDictionary(
                    col => col, 
                    col => reader[col] == DBNull.Value ? null : reader[col]
                );
                rows.Add(rowDict);
            }
            // 用System.Text.Json序列化
            return System.Text.Json.JsonSerializer.Serialize(rows);
        }
    }
}

这种方式一步到位,适合API接口直接返回JSON结果的场景。

总结

  • 快速开发优先选动态对象列表:无需实体类,灵活易用。
  • 传统场景选DataSet/DataTable:兼容现有ADO.NET代码,资源管理更安全。
  • API输出选直接转JSON:减少中间步骤,提升效率。

内容的提问来源于stack exchange,提问作者Aymane EL Jahrani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:05:17