使用OleDB读取CSV时,12:00-12:59 PM时间戳返回DBNull的问题
解决OleDbDataAdapter读取CSV时12PM时段时间戳为DBNull的问题
问题根源
OleDb读取CSV时默认扫描前8行推断列类型,如果前8行的时间戳均可正常解析为DateTime,会将列类型判定为DateTime。而12:00:00 PM至12:59:59 PM的格式在OleDb的DateTime解析逻辑中存在兼容性问题,导致被识别为无效值返回DBNull。IMEX=1未生效的原因是:该参数仅在OleDb检测到列存在混合类型时触发文本模式,此处前8行无混合类型,因此未生效。
解决方案
方案1:修改OleDb文本引擎注册表设置(全局生效)
通过修改注册表强制OleDb扫描全文件进行类型推断,并将混合类型列按文本读取:
- 32位系统注册表路径:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text - 64位系统注册表路径:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet\4.0\Engines\Text - 修改以下键值:
TypeGuessRows:设为0(表示扫描整个文件)ImportMixedTypes:设为Text
方案2:使用Schema.ini指定列类型(局部推荐)
在CSV文件同目录下创建Schema.ini文件,明确指定时间戳列为文本类型,示例如下:
[your_log_filename.csv] ColNameHeader=True Format=CSVDelimited Col1=Timestamp Text Col2=EventContent Text # 根据实际日志列添加更多字段定义
OleDb读取时会严格遵循该配置,直接将时间戳列按字符串读取,避免自动类型推断的问题。
方案3:使用CSV专用库替代OleDb(最灵活)
如果无法修改注册表或Schema文件,建议使用CSV专用处理库绕过OleDb的类型推断逻辑。示例C#代码:
using CsvHelper; using System.Data; using System.Globalization; using System.IO; public DataTable QueryLogs(string filePath) { var dataTable = new DataTable(); // 根据日志结构定义列 dataTable.Columns.Add("Timestamp", typeof(string)); dataTable.Columns.Add("Message", typeof(string)); using (var reader = new StreamReader(filePath)) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Read(); csv.ReadHeader(); while (csv.Read()) { var row = dataTable.NewRow(); row["Timestamp"] = csv.GetField<string>("Timestamp"); row["Message"] = csv.GetField<string>("Message"); dataTable.Rows.Add(row); } } return dataTable; }
内容的提问来源于stack exchange,提问作者GeoffSym
相关产品推荐
相关产品推荐

