Использование EF для вставки огромных # записей повлечет за собой значительные затраты по сравнению с более прямыми подходами, но есть несколько соображений, которые можно сделать, чтобы заметно улучшить производительность.
Во-первых, пакетная обработказапросы с изменениями сохранения будут предпочтительнее сохранения отдельных записей или попытки зафиксировать все изменения сразу.Вам придется иметь дело с исключениями, если / когда пакет не удается.(Возможно, отправляя этот пакет по одной за раз, чтобы полностью изолировать дублирующиеся строки)
Далее вы можете предварительно кэшировать ваши почтовые индексы, а не просматривать их каждую итерацию.Не загружайте всю сущность, просто кешируйте почтовый индекс и идентификатор в список в памяти: (Если сущность почтового индекса составляет чуть больше, чем просто, просто загрузите сущность) var zipCodes = db.dbzipcodes.Select(x => new {x.ZIPCODEID, x.ZIP}). ToList ();
Это потребует некоторого дополнительного внимания, когда речь идет о назначении почтового индекса клиенту в пакетных вызовах, посколькуПочтовый индекс изначально не будет известен DbContext, но может быть известен, когда добавлен второй клиент с тем же почтовым индексом.
Чтобы связать почтовый индекс без загрузки его в DbContext:
var customerZipCode = zipCodes.SingleOrDefault(x => x.ZIP = customer.ZIPCODE);
// + exists check...
var zipCode = new dbzipcode { ZIPCODEID = customerZipCode.ZIPCODEID };
db.dbzipcodes.Attach(zipCode);
customer.dbzipcode = zipCode;
// ...
Если вы загрузили весь объект почтового индекса в кэшированный список, то var zipCode = new dbzipcode ...
не требуется,просто прикрепите кешированную сущность.
Однако, если в пакете этот почтовый индекс уже был связан с DbContext, вы получите ошибку (независимо от того, кэшировали ли вы сущность или просто ID / код), таквам нужно сначала проверить почтовые индексы dbContext в памяти:
var customerZipCode = zipCodes.SingleOrDefault(x => x.ZIP = customer.ZIPCODE);
// + exists check...
var zipCode = db.dbzipcodes.Local.SingleOrDefault(x => x.ZIPCODEID == customerZipCode.ZIPCODEID)
?? new dbzipcode { ZIPCODEID = customerZipCode.ZIPCODEID };
db.dbzipcodes.Attach(zipCode);
customer.dbzipcode = zipCode;
// ...
Наконец, EF отслеживает много дополнительной информации в памяти в качестве контекста, поэтому другим соображением наряду с пакетной обработкой было бы избегать использования того же самогоDbContext во всех пакетах, скорее, открывая DbContext для каждого пакета.Когда вы добавляете элементы и вызываете SaveChanges через DbContext, он все еще отслеживает каждую добавляемую сущность.Если вы делаете пакеты по 1000 штук или около того, контекст будет отслеживать только эту 1000, а не 1000, а затем 2000, затем 3000 и т. Д. До 5 миллионов строк.