Это никогда не является тривиальной задачей для интеграции баз данных, когда записи не имеют уникальных первичных ключей во всех базах данных. Несколько недель назад я построил аналогичный интеграционный скрипт, для которого я решил использовать Entity Framework.
Первый хорошие новости. С API-интерфейсом EF DbContext
смешно легко вставить полный граф объектов и заставить EF заботиться обо всех вновь созданных первичных ключах внешних ключей. Причина, по которой это так легко, заключается в том, что когда состояние объекта изменено на Added
, все его его приклеиваются и становятся Added
, а EF формирует правильный порядок вставок. Это действительно здорово! Это заставило меня заложить основу процедуры копирования за несколько часов, что бы было много дней, если бы я сделал это в T-SQL, например. Последнее гораздо более подвержено ошибкам.
Конечно, жизнь не , что легко. Теперь плохие новости:
Это занимает тонн машинных ресурсов. Конечно, я использовал новый экземпляр контекста для каждого этапа копирования, но все же мне пришлось выполнить программу на машине с приличным процессором и достаточным количеством внутренней памяти. Точные спецификации не имеют значения, сообщение: тест с самыми большими базами данных и посмотреть, какой зверь вам нужен. Если потребление памяти не может управляться какой-либо машиной в вашем распоряжении, вам придется разделить рутину на более мелкие куски, но это потребует большего количества программ.
График предмета, который изменен на Added
, должен быть разный. Под этим я подразумеваю, что должны быть только ассоциации 1-n
, начиная с корня. Причина в том, что EF действительно отметит все объекты как Added
. Поэтому, если где-то на графике несколько ветвей ссылаются на один и тот же объект (потому что есть ассоциация n-1
), эти «новые» объекты будут умножаться, потому что EF не знает их идентичности. Пример этого может быть Company -< Customer
- < Order
> - OrderType
: когда есть только два типа заказа, вставляя один корневую компанию с 10 клиентов с 10 заказов каждый будет создавать 100 записи типа порядка вместо 2.
Так Трудная часть - найти пути вашей структуры класса, которые расходятся как можно больше. Это не всегда возможно. Если это так, вам придется сначала добавить листья сходящихся путей. В примере: сначала вставьте типы ордеров.Когда новая компания вставлена, вы сначала загружаете существующие типы заказов в контекст, а затем добавляете компанию. Теперь привяжите новые заказы к существующим типам заказов. Это можно сделать, только если вы можете сопоставлять объекты по естественным клавишам (в этом примере: имена типа заказа), но обычно это возможно.
Вы должны позаботиться о том, чтобы не вставлять несколько копий основных основных данных. Предположим, что типы заказов в предыдущем примере одинаковы во всех базах данных (хотя их первичные ключи могут отличаться!). Типы заказов из исходной базы данных не должны быть повторно вставлены в целевую базу данных. Кроме того, вы должны исправить ссылки в исходных данных на правильные записи в целевой базе данных (опять же путем сопоставления естественным ключом).
Таким образом, хотя это было не так, это было выполнимо, и работа была выполнена за относительно короткое время. Я уверен, что другие альтернативы (t-SQL, сервисы интеграции, BIDS, если они вообще выполняются) заняли бы больше времени или были бы более сложными. И проблема с ошибками в этой области заключается в том, что они могут проявиться намного позже.
Позже выяснилось, что вопросы, которые я описываю в разделе 2), связаны с извлечением исходных объектов с помощью AsNoTracking
. Посмотреть этот интересный пост: Entity Framework 6 - use my getHashCode(). Я использовал AsNoTracking
, потому что он работает лучше, и это уменьшает потребление памяти.
Имеются ли в базе данных общие данные, так что новые записи должны иметь внешние ключи к существующим записям? Это не редкость, когда база данных содержит основные данные, такие как страны, типы, ... –
Некоторые данные будут распространены. Я ожидаю, что. Таблицы клиентов и заказов из 15 баз данных потребуют объединения в одну базу данных. У меня будет 15 разных записей клиентов с одинаковыми идентификаторами, которые потребуют изменения вместе со всеми его ссылками FK на заказы. –
Вы можете просто ввести составные клавиши и использовать 1-15 в качестве первого компонента. Но если pk был iden, тогда у вас есть проблема, поскольку я не думаю, что вы можете использовать iden в составе. Нужно больше информации. Является ли этот фильтр входа равным одной базе данных? – Paparazzi