When reading a CSV file using a DataReader and the OLEDB Jet data provider, how can I control column data types?

前端 未结 4 1270
难免孤独
难免孤独 2020-11-30 06:40

In my C# application I am using the Microsoft Jet OLEDB data provider to read a CSV file. The connection string looks like this:

Provider=Microsoft.Jet.OLEDB         


        
4条回答
  •  自闭症患者
    2020-11-30 07:19

    You need to tell the driver to scan all rows to determine the schema. Otherwise if the first few rows are numeric and the rest are alphanumeric, the alphanumeric cells will be blank.

    Like Rory, I found that I needed to create a schema.ini file dynamically because there is no way to programatically tell the driver to scan all rows. (this is not the case for excel files)

    You must have MaxScanRows=0 in your schema.ini

    Here's a code example:

        public static DataTable GetDataFromCsvFile(string filePath, bool isFirstRowHeader = true)
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("The path: " + filePath + " doesn't exist!");
            }
    
            if (!(Path.GetExtension(filePath) ?? string.Empty).ToUpper().Equals(".CSV"))
            {
                throw new ArgumentException("Only CSV files are supported");
            }
            var pathOnly = Path.GetDirectoryName(filePath);
            var filename = Path.GetFileName(filePath);
            var schemaIni =
                $"[{filename}]{Environment.NewLine}" +
                $"Format=CSVDelimited{Environment.NewLine}" +
                $"ColNameHeader={(isFirstRowHeader ? "True" : "False")}{Environment.NewLine}" +
                $"MaxScanRows=0{Environment.NewLine}" +
                $" ; scan all rows for data type{Environment.NewLine}" +
                $" ; This file was automatically generated";
            var schemaFile = pathOnly != null ? Path.Combine(pathOnly, "schema.ini") : "schema.ini";
            File.WriteAllText(schemaFile, schemaIni);
    
            try
            {
                var sqlCommand = $@"SELECT * FROM [{filename}]";
    
                var oleDbConnString =
                    $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={pathOnly};Extended Properties=\"Text;HDR={(isFirstRowHeader ? "Yes" : "No")}\"";
    
                using (var oleDbConnection = new OleDbConnection(oleDbConnString))
                using (var adapter = new OleDbDataAdapter(sqlCommand, oleDbConnection))
                using (var dataTable = new DataTable())
                {
                    adapter.FillSchema(dataTable, SchemaType.Source);
                    adapter.Fill(dataTable);
                    return dataTable;
                }
            }
            finally
            {
                if (File.Exists(schemaFile))
                {
                    File.Delete(schemaFile);
                }
            }
        }
    

    You'll need to do some modification if you are running this on the same directory in multiple threads at the same time.

提交回复
热议问题