Как заставить ADO.Net использовать только System.String DataType в чтениях TableSchema

Я использую OleDbConnection для запроса таблицы Excel 2007. Я хочу заставить OleDbDataReader использовать только строку в качестве типа данных столбца.

Система просматривает первые 8 строк данных и выводит тип данных Double. Проблема в том, что в строке 9 у меня есть строка в этом столбце, а OleDbDataReader возвращает значение Null, так как оно не может быть перенесено в Double.

Я использовал эти строки подключения:

Provider = Microsoft.ACE.OLEDB.12.0; Источник данных = "ExcelFile.xlsx"; Persist Security Info = False; Расширенные свойства = "Excel 12.0; IMEX = 1; HDR = Нет"

Provider = Microsoft.Jet.OLEDB.4.0; Источник данных = "ExcelFile.xlsx"; Persist Security Info = False; Расширенные свойства = "Excel 8.0; HDR = Нет; IMEX = 1"

Глядя на reader.GetSchemaTable(). Строки [7].ItemArray [5], это dataType - Double.

Строка 7 в этой схеме коррелирует с конкретным столбцом в Excel. У меня возникают проблемы. ItemArray [5] - это столбец DataType

Возможно ли создать пользовательский TableSchema для чтения, поэтому при доступе к ExcelFiles я могу рассматривать все ячейки как текст, а не позволять системе пытаться вывести тип данных?


Я нашел полезную информацию на этой странице: Советы по чтению таблиц Excel с использованием ADO.NET

Основная особенность интерфейса ADO.NET заключается в том, как обрабатываются типы данных. (Вы заметите, что я тщательно избегал вопроса о том, какие типы данных возвращаются при чтении электронной таблицы.) Готовы ли вы к этому? ADO.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);
            }
        }
    }
}

Ответ 1

Как вы обнаружили, 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

Проверьте окончательный ответ на эту страницу.


Просто заметила, что страница, на которую вы ссылаетесь, говорит то же самое...


Обновление

Проблема, похоже, связана с самолетом JET, а не с ADO. Как только JET решит тип, он придерживается этого. Все, что после этого не действует; например, приведение значений в строку в SQL (например, Cstr ([Column])) приводит к возврату пустой строки.

В этот момент (если нет других ответов), я бы выбрал другие методы: изменение электронной таблицы; изменение реестра (не идеально, поскольку вы будете возиться с настройками для каждого другого приложения, использующим JET); Excel или сторонний компонент, который не использует JET.

Если параметр "Автоматизация" должен замедляться, возможно, просто используйте его для сохранения электронной таблицы в другом формате, который легче обрабатывать.

Ответ 3

Примечание для 64-битной ОС:

My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\Excel

Ответ 4

Я столкнулся с той же проблемой и решил, что это то, что обычно испытывают многие люди. Вот несколько решений, которые были предложены, многие из которых я попытался реализовать:


  • Добавьте в строку подключения следующее (Источник):

TypeGuessRows = 0; ImportMixedTypes = Текст

  1. Добавьте следующую строку подключения (Источник, Дополнительные обсуждения, Еще больше):

IMEX = 1; HDR = NO;

  1. Отредактируйте следующие параметры реестра, отключите "TypeGuessRows" и "ImportMixedTypes", установленный в "Текст" (Источник, Не рекомендуется, Дополнительная документация):

HKEY_LOCAL_MACHINE/Software/Microsoft/Jet/4.0/Двигатели/Excel/TypeGuessRows HKEY_LOCAL_MACHINE/Software/Microsoft/Jet/4,0/Двигатели/Excel/ImportMixedTypes

  1. Рассмотрите возможность использования альтернативной библиотеки для чтения файла excel:

  2. Отформатируйте все данные в исходном файле как Text (по крайней мере, первые 8 строк), хотя я понимаю, что обычно непрактично (Source, хотя это отношение к SSIS, но это одни и те же понятия)

  3. Используйте файл Schema.ini для определения типа данных перед импортом файла, я нашел это применительно к непосредственному использованию "Jet.OleDb", возможно, вам потребуется изменить строку соединения. Это может быть применимо только к CSV. Я не пробовал этот подход. (Источник, Связанный пост)


Никто из них не работал у меня (хотя я считаю, что они работали для других). Я придерживаюсь мнения, высказанного @Asher, что на самом деле нет хорошего решения этой проблемы. В моем программном обеспечении я просто показываю сообщение об ошибке пользователю (если любой требуемый столбец содержит пустые значения), инструктируя их форматировать все столбцы как "Текст" .

Честно говоря, я думаю, эта книга более применима к ситуации. Проблема, уже заявленная несколько раз:

  • "Тип данных в месте назначения - varchar, но предполагаемые данные тип "double" аннулирует любые данные, которые не подходят. "(Источник)

  • "Но проблема на самом деле связана с OLEDBDataReader. заключается в том, что если он видит в основном числа в столбце, он принимает все - число - если считываемый элемент строки не является числом, это просто устанавливает его в null! Ouch! "(Источник)

  • "Проблема, похоже, связана с самолетом JET, а не с ADO. JET решает этот тип, он придерживается этого ". (@Asher)

Пока я не нашел ни одного документа, зарегистрированного в официальном качестве, я думаю, что очень ясно, что это намеренное дизайнерское решение и просто как Библиотека базы данных Jet. Я стесняюсь назвать эту библиотеку совершенно бесполезной, потому что многие считают, что некоторые из этих решений работают, но до сих пор для моего проекта я пришел к выводу, что эта библиотека не может читать несколько типов данных в одном столбце и плохо подходит для общего поиска данных.