2012-04-11 4 views
42

При использовании DbContext в первом сценарии базы данных я обнаружил, что добавление и удаление объектов происходит очень медленно по сравнению с ObjectContext. Если добавить 2000 объектов и сохранить изменения в конце, DbContext в 3 - 5 раз медленнее, чем ObjectContext (кстати, я знаю, что добавление большого количества объектов будет лучше использовать SqlBulkCopy, но это не так). Если сохранение изменений после каждого добавления DbContext по-прежнему почти в два раза медленнее. Когда дело доходит до удаления, это даже ухудшается: при сохранении в конце всех абзацев сущности DbContext примерно в 18 раз медленнее ObjectContext.DbContext очень медленно при добавлении и удалении

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

Inserting 2000 entities via DbContext saving changes at the end: 2164ms 
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms 
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms 
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms 
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms 
Deleting 2000 entities via DbContext saving changes at the end: 4794ms 
Deleting 2000 entities via ObjectContext saving changes at the end: 261ms 
Deleting 2000 entities via DbContext saving changes after each object deletion: 25536ms 
Deleting 2000 entities via ObjectContext saving changes after each object deletion: 2110ms 

Я попытался с помощью EF 4.3 в VC 2010 и EF 5.0 Beta 2 в VS 11 с почти такими же результатами. Я использовал шаблоны T4, предоставленные «EF 4.x POCO Entity Generator для C#», «EF 4.x DbContext Generator для C#» и «EF 5.x DbContext Generator для C#».

Что может быть неправильным? Согласно результатам тестирования я никогда не использовал бы DbContext в приложении, которое должно добавлять или удалять объекты (что делает DbContext к сожалению непригодным для меня).

Я положил приложений тестирования консоли на моем веб-сервере: EF 4.3 DbContext Test, EF 5.0 DbContext Test

Любые идеи/исправления приветствуются.

+0

Две ссылки в дополнение к Ladislavs: http://stackoverflow.com/questions/5943394/why-is-inserting-entities-in-ef-4-1-so-slow-compared-to-objectcontext/5943699 # 5943699 и http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework/5942176#5942176 – Slauma

ответ

86

Попробуйте добавить это к вашим тестам DbContext:

dbContext.Configuration.AutoDetectChangesEnabled = false; 

// Now do all your changes 

dbContext.ChangeTracker.DetectChanges(); 
dbContext.SaveChanges(); 

и попытаться запустить тесты снова.

В DbContext API было внесено некоторое архитектурное изменение, которое проверяет изменения сущностей каждый раз, когда вы Add, Attach или Delete ничего из контекста. В ObjectContext API это обнаружение запускается только при запуске SaveChanges. Это лучшее решение для большинства распространенных сценариев, но для этого требуется специальная обработка для массовой обработки данных.

+1

Thanks Ladislav. Это действительно послужило причиной проблемы производительности при добавлении/удалении многих объектов и сохранении изменений в конце. После установки параметра AutoDetectChangesEnabled в значение false результат был почти таким же, как с ObjectContext.Но все же единственная вставка и особенно одиночное удаление, за которым следует SaveChanges, медленнее по сравнению с ObjectContext, даже если я устанавливаю AutoDetectChangesEnabled в false и вызывается DetectChanges перед SaveChanges. Удаление 2000 объектов по-прежнему занимало около 17 секунд при использовании DbContext, а –

+0

... для использования объекта ObjectContext потребовалось около 2,1 с. Я предполагаю, что это просто из-за этих изменений в отслеживании изменений. Кстати: Не могли бы вы объяснить, почему проверка изменений каждый раз при добавлении, прикреплении или удалении является лучшим решением для большинства распространенных сценариев? –

+3

@ JürgenBayer: Я воспроизвел большую разницу в производительности для «DeleteObject/Remove», описанную в вашем комментарии. Разница исчезает, если вы удаляете «DetectChanges» из кода (который на самом деле не нужен, если вы только добавляете и удаляете сущности). Но тем не менее я понимаю, что 'ObjectContext.SaveChanges()' вызывает 'DetectChanges' внутри, а' DbContext.SaveChanges() 'не работает, когда' AutoDetectChanges' отключен. Таким образом, вызов 'DetectChanges' +' DbContext.SaveChanges() '(с отключенным AutoDetectChanges) должен совпадать с вызовом' ObjectContext.SaveChanges() '- в теории. – Slauma

11

В EF6 теперь вы можете использовать AddRange и RemoveRange на DbSet.

Из к документации по ссылкам:

Обратите внимание, что если AutoDetectChangesEnabled установлено значение истина (значение по умолчанию), то DetectChanges будет вызываться один раз перед {добавление, удаление} любые объекты и не будет снова называться. Это означает, что в некоторых ситуациях {Add, Remove} Range может выполнять значительно лучше, чем вызов {Add, Remove} несколько раз.

Смежные вопросы