oledb 到 csv 异常的奇怪行为

Strange behavior of exception with oledb to csv

我有一个应用程序,它通过 ole-db 连接到 csv-data。 csv 数据被加载到数据 table 中。然后我遍历 table 的数据行。对于每个数据行,都会调用一个函数,该函数将数据插入 mysql-db.

private void ConvertCSVDocument()
{
    try
    {
        using (var dataSet = base.Source.CreateDataSet())
        {
            using (var dataTable = dataSet.Tables[0])
            {
                base.Progress(dataTable.Rows.Count, 0);

                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    try
                    {
                        this.ConvertCSVDocumentRow(dataTable.Rows[i]);
                    }
                    catch (Exception e)
                    {
                        base.Report($"Row {i.ToString("0000")} {e}");
                    }
                    finally
                    {
                        base.Progress(dataTable.Rows.Count, i);
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        base.Report($"Fatal error: {e}");
    }
}

当我执行此代码时,在创建我的数据集的行上抛出异常 (using var dataSet = base.Source.CreateDataSet())

我收到以下消息:

Fatal error: System.ArgumentException: illegal OleAut-Date. bei System.DateTime.DoubleDateToTicks(Double value) bei System.Data.OleDb.ColumnBinding.Value_DATE() bei System.Data.OleDb.ColumnBinding.Value() bei System.Data.OleDb.OleDbDataReader.GetValues(Object[] values) bei System.Data.ProviderBase.DataReaderContainer.CommonLanguageSubsetDataReader.GetValues(Object[] values) bei System.Data.ProviderBase.SchemaMapping.LoadDataRow() bei System.Data.Common.DataAdapter.FillLoadDataRow(SchemaMapping mapping) bei System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue) bei System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords) bei System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) bei System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) bei System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) bei FooKonvert.Context.Csv.CsvContext.CreateDataSet() in D:\Projekte\csharp\Tools\Foo\FooKonvert\Context\Csv\CsvContext.cs:Zeile 42. bei FooKonvert.Converter.FooConverter.ConvertCSVDocument() in D:\Projekte\csharp\Tools\Foo\FooKonvert\Converter\FooConverter.cs:Zeile 395.

当我注释掉行时 this.ConvertCSVDocumentRow(dataTable.Rows[i]); 没有抛出异常,并且通过数据行的迭代成功。

有人可以解释一下发生了什么吗?错误发生在该行甚至被调用之前,当抛出异常时,这个函数甚至还没有被调用。

#

以下是我创建数据集的方式:

public DataSet CreateDataSet()
{
    string connectionString = $"provider=Microsoft.Jet.OLEDB.4.0; data source={this.FilePath};Extended Properties=\"Text;HDR=yes;\"";

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        connection.Open();

        OleDbDataAdapter adapter = new OleDbDataAdapter($"SELECT * FROM [{this.FileName}]", connection);

        var dataSet = new DataSet();
        var dataTable = new DataTable();

        adapter.Fill(dataTable);
        dataSet.Tables.Add(dataTable);

        return dataSet;
    }
}

这是 ConvertSCVDocumentRow 函数的抽象版本:

try
{
    var forename = dataRow["some_column_name_1"].ToString();
    var surename = dataRow["some_column_name_2"].ToString();

    int person_ident = GetIdentForPerson(forename,surename);

    if (person_ident <= 0)
    {
        InsertPerson(forename,surename);                
    }
}
catch(Exception e)
{
    throw new Exception("Failed to convert person!", e);
}

就像 Rune Grimstadt 提到的那样,还有其他选项可以将 csv 文件读取到数据集。这是我在互联网上找到的 FileStream 的解决方案:

public DataTable CreateDataTable()
{
    DataTable dt = new DataTable();
    FileStream aFile = new FileStream(this.FilePath, FileMode.Open);
    using (StreamReader sr = new StreamReader(aFile, System.Text.Encoding.Default))
    {
        string strLine = sr.ReadLine();
        string[] strArray = strLine.Split(';');

        foreach (string value in strArray)
            dt.Columns.Add(value.Trim());

        DataRow dr = dt.NewRow();

        while (sr.Peek() > -1)
        {
            strLine = sr.ReadLine();
            strArray = strLine.Split(';');
            dt.Rows.Add(strArray);
        }
    }
    return dt;
}

这对我有用。