У меня есть приложение ASP .NET MVC, для которого я пытаюсь написать функцию импорта.
У меня есть некоторые особенности, например, я использую Entity Framework v4 в приложении MVC , но я особенно заинтересован в алгоритме , который будет работать лучше, предпочтительно с объяснение того, что это за производительность и почему.
Эта операция будет выполняться асинхронно, поэтому время выполнения не так важно, как использование ОЗУ.
Я должен отметить, что есть несколько вещей (база данных является основной), которые я был вынужден унаследовать, и из-за нехватки времени я не смогу очистить их до более поздней даты.
Детали
Функция импорта заключается в том, чтобы взять CSV-файл в памяти (который был экспортирован из Sales Force и загружен) и объединить его с существующей таблицей базы данных. Процесс должен быть подготовлен к:
Обновление существующих записей, которые могли быть изменены в CSV, без удаления повторного добавления записи базы данных, чтобы сохранить первичный ключ каждой записи.
Добавление и удаление любых записей по мере их изменения в файле CSV.
Текущая структура таблицы CSV и базы данных такова:
Таблица и CSV содержат 52 столбца.
Каждый столбец в существующей схеме базы данных является полем VARCHAR (100) ; Я планирую оптимизировать это, но не могу в течение текущего периода времени.
Сервер базы данных - MS SQL.
В CSV-файле содержится около 1700 строк данных. Я не вижу этого числа, превышающего 5000, так как, похоже, уже много повторяющихся записей.
В настоящее время я планирую только импортировать 10 из этих столбцов из CSV, остальные поля таблицы останутся пустыми, а позже я буду удалять ненужные столбцы.
CSV-файл считывается в DataTable , чтобы с ним было легче работать.
Сначала я думал, что поле ContactID в моем CSV Sales Force было уникальным идентификатором, хотя после выполнения некоторых тестовых импортов кажется, что в самом файле CSV есть ноль уникальных полей, по крайней мере, что я могу найти.
Учитывая это, я был вынужден добавить поле первичного ключа в таблицу контактов, чтобы другие таблицы могли поддерживать действительные отношения с любым данным контактом. Однако это, очевидно, не позволяет мне просто удалять и заново создавать записи при каждом импорте.
BEGIN EDIT
Мне ясно, что то, чего я пытался достичь, выполнить обновления существующих записей базы данных, когда не существует никакой связи между таблицей и CSV, просто не может быть достигнуто.
Это было не так много, что я не знал об этом заранее, но больше, что я надеялся, была просто какая-то блестящая идея, о которой я не думал, которая могла бы сделать это.
Имея это в виду, я решил в своем алгоритме просто предположить, что ContactID является уникальным идентификатором, а затем посмотреть, сколько дубликатов у меня получилось.
Я собираюсь найти возможное решение в качестве ответа ниже. И алгоритм, и фактическая реализация. Я оставлю это на несколько дней, потому что я бы предпочел принять в качестве ответа чье-то лучшее решение.
Вот некоторые вещи, которые я нашел после реализации моего решения ниже:
- Мне пришлось сузить строки, предоставляемые CSV, чтобы они соответствовали тем строкам, которые импортируются в базу данных.
- SqlDataReader прекрасно работает, и наибольшее влияние оказывают отдельные запросы UPDATE / INSERT, которые выполняются.
- Для полностью нового импорта начальное чтение элементов в память не замечается пользовательским интерфейсом, процесс вставки занимает около 30 секунд.
- Было только 15 дублированных идентификаторов, пропущенных при новом импорте, что составляет менее 1% от общего набора данных. Я посчитал это приемлемой потерей, поскольку мне сказали, что база данных отдела продаж в любом случае подвергнется очистке. Я надеюсь, что идентификаторы могут быть восстановлены в этих случаях.
- Я не собирал никаких метрик ресурса во время импорта, но с точки зрения скорости это нормально, потому что индикатор прогресса, который я реализовал, чтобы предоставить обратную связь пользователю.
END EDIT
Ресурсы
Учитывая размер выделения каждого поля, даже с этим относительно небольшим количеством записей, меня больше всего беспокоит объем памяти, который может быть выделен во время импорта.
Приложение не будет работать в общей среде, поэтому в этом отношении есть место для вдохновения. Кроме того, эта конкретная функция будет запускаться только один раз в неделю или около того, вручную.
Моя цель, по крайней мере, быть в состоянии комфортно работать на полуотделенной машине. Спецификации машины являются переменными, поскольку приложение может в конечном итоге продаваться как продукт (хотя, опять же, не предназначенный для общей среды).
С точки зрения времени выполнения процесса импорта, как уже упоминалось, это будет асинхронно, и я уже собрал несколько вызовов AJAX и индикатор выполнения. Так что я думаю, что где-нибудь до минуты или двух будет в порядке.
Решение
Я нашел следующий пост, который, кажется, близок к тому, что я хочу:
Сравните две таблицы данных, чтобы определить строки в одной, но не в другой
Мне кажется, что выполнение поиска по хеш-таблице - правильная идея. Однако, как уже упоминалось, если мне удастся избежать загрузки как CSV, так и таблицы контактов в память полностью, это было бы предпочтительным, и я не вижу возможности избежать этого с помощью метода хеш-таблицы.
Одна вещь, которую я не уверен в том, как добиться этого, - как вычислить хеш каждой строки для сравнения, когда один набор данных является объектом DataTable, а другой - элементами EntitySet of Contact.
Я думаю, что если я не хочу вручную выполнять итерацию по каждому значению столбца для вычисления хэша, мне потребуется, чтобы оба набора данных были одного и того же типа объекта, если у кого-то нет каких-либо причудливых решений.
Лучше ли мне просто забыть Entity Framework для этой процедуры? Я, конечно, потратил много времени, пытаясь дистанционно выполнить массовые операции, поэтому я более чем счастлив удалить его из уравнения.
Если что-то не имеет смысла или отсутствует, прошу прощения, я очень устал. Просто дайте мне знать, и я исправлю это завтра.
Я ценю любую помощь, которая может быть предложена, так как я начинаю отчаяться. Я потратил больше времени на то, чтобы приблизиться к этому, чем планировал.
Спасибо!