代码之家  ›  专栏  ›  技术社区  ›  Keith Sirmons

如何强制ADO.Net只使用readers表模式中的System.String数据类型

  •  11
  • Keith Sirmons  · 技术社区  · 15 年前

    我正在使用OleDbConnection查询excel2007电子表格。我想强制OleDbDataReader仅使用字符串作为列数据类型。

    系统正在查看前8行数据并推断数据类型为Double。问题是,在第9行,我在该列中有一个字符串,而OleDbDataReader返回一个空值,因为它无法转换为Double。

    我使用了以下连接字符串:

    提供商=Microsoft.ACE.OLEDB.12.0;数据源=“ExcelFile.xlsx”;Persist Security Info=False;扩展属性=“Excel 12.0;IMEX=1;HDR=否“

    查看reader.GetSchemaTable().Rows[7].ItemArray[5],它的数据类型是Double。

    此架构中的第7行与Excel中我遇到问题的特定列相关联。ItemArray[5]是它的数据类型列


    Tips for reading Excel spreadsheets using ADO.NET

    ADO.NET接口的主要问题是如何处理数据类型(您会注意到我一直在小心地避免在读取电子表格时返回哪些数据类型的问题。)您准备好了吗?NET扫描前8行数据,并据此猜测每列的数据类型。然后它尝试将该列中的所有数据强制为该数据类型,每当强制失败时返回NULL!

    非常感谢。
    基思


    using (OleDbConnection connection = new OleDbConnection(BuildConnectionString(dataMapper).ToString()))
    {
        connection.Open();
        using (OleDbCommand cmd = new OleDbCommand())
        {
            cmd.Connection = connection;
            cmd.CommandText = SELECT * from [Sheet1$];
            using (OleDbDataReader reader = cmd.ExecuteReader())
            {
                using (DataTable dataTable = new DataTable("TestTable"))
                {
                    dataTable.Load(reader);
                    base.SourceDataSet.Tables.Add(dataTable);
                }
            }
        }
    }
    
    4 回复  |  直到 5 年前
        1
  •  7
  •   Thomas    15 年前

    正如您所发现的,OLEDB使用的是Jet,它的调整方式受到限制。如果设置为使用OleDbConnection读取Excel文件,则需要设置 HKLM\...\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows

    也就是说,如果您愿意使用替代引擎从Excel文件中读取,您可以考虑尝试 ExcelDataReader . 它将所有列作为字符串读取,但允许您使用dataReader.Getxxx方法获取类型化值。这是一个样本 DataSet :

    DataSet result;
    const string path = @"....\Test.xlsx";
    using ( var fileStream = new FileStream( path, FileMode.Open, FileAccess.Read ) )
    {
        using ( var excelReader = ExcelReaderFactory.CreateOpenXmlReader( fileStream ) )
        {
            excelReader.IsFirstRowAsColumnNames = true;
            result = excelReader.AsDataSet();
        }
    }
    
        2
  •  2
  •   Simon_Weaver    12 年前

    注意:对于64位操作系统:

    My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\Excel
    
        3
  •  1
  •   Asher    15 年前

    在上查看最终答案 this page .


    只是注意到你提到的页面上写着同样的东西。。。


    更新

    问题似乎出在喷气发动机本身,而不是ADO。一旦JET决定了类型,它就会坚持下去。之后所做的一切都没有效果;类似于将值强制转换为SQL中的字符串(例如Cstr([Column]),只会返回一个空字符串。

    在这一点上(如果没有其他答案),我会选择其他方法:修改电子表格;修改注册表(不太理想,因为你会弄乱JET使用的其他应用的设置);Excel自动化或不使用JET的第三方组件。

    如果自动化选项是慢,那么也许只是使用它来保存一个不同的格式,更容易处理的电子表格。

        4
  •  0
  •   Community CDub    8 年前

    我也遇到过同样的问题,我认为这是很多人经常经历的事情。以下是一些建议的解决方案,其中许多我已经尝试实施:


    1. 将以下内容添加到连接字符串中( Source ):

    TypeGuessRows=0;ImportMixedTypes=文本

    1. 将以下内容添加到连接字符串中( Source , More Discussion , Even More ):

    IMEX=1;HDR=否;

    1. Source , Not Recommended , More Documentation ):

    Hkey\ U Local\ U Machine/Software/Microsoft/Jet/4.0/Engines/Excel/TypeGuessRows

    1. 考虑使用另一个库来读取Excel文件:

    2. 将源文件中的所有数据格式化为文本(至少前8行),尽管我知道这通常是不切实际的( Source

    3. 在导入文件之前,使用Schema.ini文件定义数据类型,我发现这与直接使用“Jet.OleDb”有关,可能需要修改连接字符串。这可能只适用于CSV的我没有尝试过这种方法( Source , Related Post )


    这些都没有为我工作过(尽管我相信他们为其他人工作过)。我同意@Asher的观点,这个问题确实没有好的解决办法。在我的软件中,我只是向用户显示一条错误消息(如果任何必需的列包含空值),指示他们 format all columns as "Text" .

    老实说,我想 this book 更适用于这种情况。这一问题已经多次提到:

    • “目标的数据类型是varchar,但假定的数据 “double”类型将使任何不适合的数据无效。“( )

    • 如果它在一列中看到的大部分是数字,那么它会假设所有的东西 Source )

    • “问题似乎出在喷气发动机本身,而不是ADO。一次 喷气机决定了它的类型,它坚持它。”(@Asher)

    虽然我还没有发现任何官方的文件,我认为这是一个非常明确的,这是一个有意的设计决定,只是如何 Jet Database Library 作品。我不太愿意称这个库完全无用,因为我认为对于许多人来说,这些解决方案中的一些确实有效,但到目前为止,对于我的项目,我得出的结论是,这个库不能在一个列中读取多个数据类型,不适合一般的数据检索。