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




