C#使用OleDb导入CSV到DataTable欧洲格式日期字段为空问题求解
问题根因
你遇到的空值问题是OLEDB的Jet引擎自动类型推断导致的:引擎默认会扫描CSV前几行数据自动判断列类型,识别到疑似日期的内容时,会调用当前系统默认区域的日期格式解析,若系统区域默认是MM/dd/yyyy的月/日/年格式,遇到24/12/2021这类日部分大于12的欧洲格式日期时,解析失败就会返回空值。
解决方案
方案1:修改连接字符串降低推断错误概率
在连接字符串的Extended Properties中新增IMEX=1和MaxScanRows=0参数,前者强制混合类型列按文本读取,后者要求引擎扫描全表数据判断类型而非仅扫描前几行,修改后的连接字符串代码如下:
string sql = @"SELECT * FROM [" + fileName + "]"; // 新增IMEX和MaxScanRows参数 using (OleDbConnection connection = new OleDbConnection( @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + $";Extended Properties=\"Text;HDR={header};IMEX=1;MaxScanRows=0\"")) using (OleDbCommand command = new OleDbCommand(sql, connection)) using (OleDbDataAdapter adapter = new OleDbDataAdapter(command)) { DataTable dataTable = new DataTable(); dataTable.Locale = CultureInfo.CurrentCulture; adapter.Fill(dataTable); intCurrentTableRowCount = dataTable.Rows.Count; return dataTable; }
方案2:用schema.ini强制指定列类型(最稳定)
如果方案1仍无法解决,直接在CSV所在目录(即pathOnly参数对应的目录)下创建名为schema.ini的配置文件,明确指定第12、13、14列为文本类型,完全关闭引擎的自动类型推断,配置文件示例如下:
[你要读取的CSV文件名.csv] ColNameHeader=True # 如果你的CSV第一行不是表头则改为False Format=Delimited(,) # 按实际分隔符调整,Tab分隔则写TabDelimited Col12=你的第12列表头名 Text Col13=你的第13列表头名 Text Col14=你的第14列表头名 Text
配置完成后直接运行原有代码即可,这三列会按原始文本读取,不会自动做日期转换,后续如果需要转日期类型,可以手动调用DateTime.ParseExact指定dd/MM/yyyy格式解析,不会出现空值。
方案3:更换CSV读取组件
如果不想依赖OLEDB,可以改用CsvHelper等专门的CSV处理库,手动控制每一列的解析规则,完全避开Jet引擎的类型推断问题。
内容的提问来源于stack exchange,提问作者LJH
相关产品推荐
相关产品推荐

