You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OracleDataAdapter.Fill()隐式转Oracle Date为DateTime的格式适配问题

解决ODP.NET中Oracle Date转DateTime导致格式不一致的问题

我完全懂你的困扰——不想改SQL脚本,也不想挨个遍历单元格解析日期,还得严格保持Oracle原生的日期输出格式。下面几个方案完美适配你的需求,不用动SQL,还能自动处理所有日期列:

方案1:直接用OracleDataReader读取,跳过DataSet的自动转换

这是最高效直接的方式,绕开OracleDataAdapter自动转DateTime的逻辑,直接获取Oracle原生的日期字符串格式:

using (var oracleCommand = new OracleCommand(query, Connection))
{
    var result = new List<T>();
    using (var reader = oracleCommand.ExecuteReader())
    {
        while (reader.Read())
        {
            var data = new T();
            for (int i = 0; i < reader.FieldCount; i++)
            {
                // 自动识别Oracle Date类型列
                if (reader.GetProviderType(i) == OracleDbType.Date)
                {
                    // 用OracleDateTime的ToString()获取原生格式
                    data[i] = reader.GetOracleDateTime(i).ToString();
                }
                else
                {
                    data[i] = reader[i].ToString();
                }
            }
            result.Add(data);
        }
    }
}

这个方案省去了DataSet的中间环节,自动适配任意位置的Date列,不管你的SQL语句怎么变,都能正确处理。

方案2:自定义DataSet填充逻辑,将Date列转为字符串

如果你不想放弃DataSet的使用,可以先修改表结构的列类型,再手动填充数据,确保Date列以字符串形式存储:

using (var oracleCommand = new OracleCommand(query, Connection))
{
    DataSet dataSet = new DataSet();
    // 第一步:获取表结构,把Date列类型改成string
    using (var schemaReader = oracleCommand.ExecuteReader(CommandBehavior.SchemaOnly))
    {
        DataTable schemaTable = schemaReader.GetSchemaTable();
        DataTable dataTable = new DataTable();
        foreach (DataRow schemaRow in schemaTable.Rows)
        {
            string colName = schemaRow["ColumnName"].ToString();
            Type colType = (Type)schemaRow["DataType"];
            // 识别Oracle Date类型,替换列类型为string
            if (schemaRow["ProviderType"].ToString() == "Date")
            {
                colType = typeof(string);
            }
            dataTable.Columns.Add(colName, colType);
        }
        dataSet.Tables.Add(dataTable);
    }
    // 第二步:手动填充数据,处理Date列
    using (var dataReader = oracleCommand.ExecuteReader())
    {
        DataTable dataTable = dataSet.Tables[0];
        while (dataReader.Read())
        {
            DataRow row = dataTable.NewRow();
            for (int i = 0; i < dataReader.FieldCount; i++)
            {
                if (dataReader.GetProviderType(i) == OracleDbType.Date)
                {
                    row[i] = dataReader.GetOracleDateTime(i).ToString();
                }
                else
                {
                    row[i] = dataReader[i].ToString();
                }
            }
            dataTable.Rows.Add(row);
        }
    }
    // 后续的结果转换逻辑和你原来的代码完全一致
    var result = new List<T>();
    foreach (DataTable table in dataSet.Tables)
    {
        foreach (DataRow row in table.Rows)
        {
            var data = new T();
            foreach (DataColumn column in table.Columns)
            {
                data[column.Ordinal] = row[column].ToString();
            }
            result.Add(data);
        }
    }
}

这个方案保留了你原有的DataSet处理流程,同时自动处理所有Date列,完全不用修改SQL。

方案3:设置Oracle会话的日期格式(辅助优化)

如果希望.NET DateTime的ToString()输出和Oracle原生格式完全匹配,可以在打开连接后设置会话的NLS_DATE_FORMAT:

using (var connection = new OracleConnection(connectionString))
{
    connection.Open();
    // 获取当前会话的全球化配置
    OracleGlobalization globalization = connection.GetSessionInfo();
    // 设置为你需要的格式,比如Oracle默认的DD-MON-RR或者自定义的YYYY-MM-DD HH24:MI:SS
    globalization.DateFormat = "YYYY-MM-DD HH24:MI:SS";
    connection.SetSessionInfo(globalization);

    // 后续的查询逻辑...
}

这个设置可以让Oracle返回的日期格式统一,结合前面的方案1或2,能确保你拿到的日期字符串和Oracle直接输出的完全一致。


内容的提问来源于stack exchange,提问作者Will Paul

火山引擎 最新活动