Как стать автором
Обновить

Комментарии 23

Искал подобный инструмент, написал свой на node.js + Delphi, но возможно ваш удобнее.
Подскажите — а можете добавить поддержку ODBC, для использования любых SQL БД?
У меня есть еще одно подобное приложение, которое может конвертировать данные из одной СУБД в другую СУБД (MySQL, MSSQL, Access, Firebird), там есть поддержка ODBC. Вот ссылка, если интересно: yadi.sk/d/JQRvh2BOT7vqtg
Когда-нибудь перенесу тот функционал в ImportExportDataSql
как обрабатывается присутствие спец символов (табуляция, перевод строки и т.д.) в ячейках при импорте из Excel?
Я думал как есть так и обрабатывается, без изменений. Оказалось, что табуляция заменяется на пробел, а переход на новую строку заменяется на пустую строку.
Буду исправлять, спасибо за вопрос!

Уважаемый автор, спасибо во-первых.
Во-вторых вопрос: где то раз в квартал приходится заниматься одной странной хренью — качать с одного гос.сайта гигантский XML (2-3 гига) с чудовищной структурой, которую распарсить в csv без падения может лишь одна утилитка (не важно какая, в итоге csv).
Далее этот csv я должен импортировать через "Import and Export Data (64-bt)" с полной перезаписью в таблицу.
Т.к. длина текстовых полей велика и заголовки полей периодически могут "плавать" написал сам для себя инструкцию чтобы печаль нет так сильно меня брала.
один из хаков по инструкции — согласно совету stack вручную выкручивать длину поля до 8000 символов.
В общем там так себе мастер (хотя раз в квартал терпимо).
Есть ли смысл тратить время на тест Вашего изделия, будет ли оно удобнее для таких задач?

Я пробовал обрабатывать большие CSV и проблем не возникало. Можно поиграться с количеством записей блоков, чтобы оптимизировать скорость загрузки. Если есть возможность передать мне Ваш CSV файл (хотя бы часть), то я могу попробовать его загрузить в MSSQL и прислать вам готовый настроечный XML-файл, а Вам будет достаточно настроить соединение с БД и нажать кнопку «Выполнить обработку выбранных задач».
Попробуйте подход описанный в комментарии ниже.

С другой стороны — если всего 1 раз в квартал парсится файл, то можно и костылями решить вопрос.
Могу подкинуть другой вариант:
Берется linq2db
Берется любая библиотека которая CSV парсит и потоково возвращает IEnumerable<string[]>, тут я не помощник.

И пишется что-то такое
var csvItems = CSVParser.Parse("filename");

using (var db = new DataConnection(...))
{
    db.BulkCopy(
       csvItems.Select(csv => new DestinationEntity{
          Field1 = int.Parse(csv[0]),
          Field2 = double.Parse(csv[1]),
          LongStr = csv[2],
          ...
       })
    );
}

Гарантирую, что если отключите индексы, данные влетят, даже чай не успеете заварить.
Для баз данных, которые поддерживают такие вставки, и того быстрее. Будут посланы параметризированные запросы и не надо беспокоиться о длине полей.
А где же цикл обработки построчно и заливка в БД блоками? Если таким образом заливать несколько Гб разом, то транзакция будет переполнять диск и операция будет очень долгой, либо будет System.OutOfMemoryException.
Это проверено личным опытом.
P.S.: Даже системная утилита bcp пишет блоками по 1000 записей, не задумывались почему? Правда bcp фиксирует изменения одной транзакцией и это происходит долго (забивается диск), а ImportExportDataSql фиксирует изменения сразу после записи блока.
Вся магия внутри, по умолчанию обрабатываются пачки по 1000 записей, и это конфигурируется. Догадываетесь почему?

Вы пропустили мое описание что данные должны представляться как IEnumerable — это не все записи сразу, ни в коем случае.
var csvItems = CSVParser.Parse("filename");

Этот код означает чтение всего файла целиком или частями? Если целиком, то будет System.OutOfMemoryException, а если частями то нужно весь код внести в цикл, чтобы записи из файла считывались блоками.
Не учить же вас как пользоваться C#. Вот примерная реализация парсера. Пишу на коленке, важен подход.
public IEnumerable<string[]> ParseCsv(string fileName)
{
   using (var file = new System.IO.StreamReader(fileName))
   {
       string line;
       while((line = file.ReadLine()) != null)  
       {  
            yield return line.Split(‘\t’);
       }
    }
}

linq2db внутри считывает из этого энумератора только 1000 записей и запихивает это в BulkCopy (для MSSQL) или готовит компактный SQL с параметрами на всю 1000 записей. Объекты больше не нужны и их подберет GC.
Процесс повторяется пока до конца файла не дойдем. Энумератор диспозится и файл закрывается.

Точно также можно взять данные IEnumerable из одной базы и закинуть в другую. Не важно сколько записей в исходной таблице, хоть миллионы.
А как linq2db считывает 1000 записей, в отдельном потоке?
Если нет, то тогда linq2db будет ждать, пока не прочитается весь файл и при большом объеме файла приложению может не хватить памяти.
Вы не понимаете что такое энумераторы и роль yield return в коде парсера.

Я бы советовал подучить эту часть.
Как только, кто-то начинает энумерацию, создается стейт машина (класс в который превращается ParseCsv метод компилятором) и при вызове метода Next в энумераторе из файла читается одна линия, не больше. Когда файл заканчивается Next вернет false — все мы перебрали все линии.

Нет планов пустить приложение в open-source, чтобы сообщество могло предлагать свои доработки?

У меня уже есть один проект в open-source на github: программа для заметок, возможно и этот выложу, если будет хоть немного желающих его доработать.

Выкладывайте, хуже не будет)

С одной стороны прикольный pet-project и Вы явно молодец, что поделились результатом, а не просто статью на Хабр запилили. Лайк и плюс в карму.

Но объективно — велосипед же?) Есть уже написанные проф. среды для визуальной разработки ETL-процедур. Talend вообще бесплатен и функциональность на несколько порядков выше. Разворачивается за 10 минут и еще минут за 10 выкачивает всякие доп.библиотеки. Явно меньше времени, чем на написание вашего тула ушло. А скомпилированный .jar ETL-процедуры можно хоть в cron выполнять, хоть любым win scheduler.
Благодарю за хороший отзыв!
Согласен, что велосипед, но хочется иметь простой инструмент без установки (портативный), чтобы взял и перенес на другой компьютер без проблем, а в какой-то момент доработал под себя.

Если продукт бесплатный, то предлагаю выложить код и сам проект в GitHub или в GitLab.
Как на это смотрите?

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