2012-03-08 2 views
1

У нас есть огромная проблема с производительностью в нашем приложении, мы собираем данные из разных систем и сохраняем их в нашей БД, чтобы потом генерировать некоторые отчеты.Массовые вставки с EF4.2

Мы используем Entity framework 4.2 и DbSets, есть ли лучший способ делать массовые вставки, а затем метод Add для каждого объекта на DbSet? Потому что есть огромные проблемы с производительностью Добавление логики

oneThousandCustomers.Foreach(c => context.Customers.Add(c)); //This will take a minute 
context.SaveChanges(); //This takes under a second 

Я предполагаю, что метод добавляемый делать много Lookups и т.д. и прочее под капотом, но я просто хочу, чтобы ссыпать вставить эти данные. Является ли это возможным?

ответ

1

Хорошо, так что дело здесь в том, что EF делает много вещей под кулисами, когда вы добавляете элемент в коллекцию.

Действительно большая вещь с точки зрения производительности состоит в том, что она вызывает функцию DetectChanges() автоматически для каждой команды add, которая перечисляет весь граф объекта.

Это означает, что если у вас есть большое количество элементов, которые отслеживаются текущим контекстом EF, это вызовет некоторые серьезные проблемы с производительностью.

Вот несколько советов по улучшению производительности. В качестве сравнения я могу вставить 1000 довольно простых объектов без FK в EF менее чем за 1/2 секунды.

  • Убедитесь, что вы используете новый экземпляр контекста EF для вашего запроса, это будет гарантировать, что ваш график изменения мала, так что добавьте будет довольно быстро.
  • Поворот автоматическое определение изменения в кодекс DbContext

отключить автоматическое обнаружение изменений

context.Configuration.AutoDetectChangesEnabled = false; 

При отключении AutoDetectChanges вам нужно быть немного осторожным, поскольку это означает, что большая часть EF automagic отключен, поэтому вы можете получить некоторые странности, особенно если вы используете свойства навигации или обновляете существующие объекты. Чтобы решить эти проблемы, вызовите DetectChanges непосредственно перед вызовом SaveChanges. Это снизит производительность и не понадобится с помощью простых операций добавления, поэтому в вашем примере вы, вероятно, можете обойтись без этого.

Эта статья MSDN говорит об этом (обратите внимание, даже если его EF 5 его же в 4) http://msdn.microsoft.com/en-us/library/gg696177%28v=vs.103%29.aspx

+0

Мы используем структуру CQRS, и контекст вводится в запрос, изменение поведения контекста является немного опасным, поскольку нет гарантии, что другие части Command-logic НЕ будут использовать контекст после того, как вы измените поведение контекста. – Anders

+0

Производительность опасна и связана с компромиссами, если вы хотите использовать преимущества EF, вам нужно либо жить с проблемами производительности, либо вручную управлять контекстом для оптимизации производительности. Если вы не хотите этого делать, и вам также нужна производительность, не используйте EF. Однако я делаю то же самое с CQRS, обмен сообщениями и массовым импортом и EF (для запросов и записи), и он отлично работает. –

+0

Мы выбираем этот вариант, потому что так легко изменить существующий в нем код. Все тесты Unit и Scenario являются зелеными, поэтому он выглядит как работающий! Благодаря! – Anders

0

Вы можете использовать LinqEntityDataReader для выполнения SqlBulkCopy в коллекции сущностей, которая улучшит производительность, введите описание ссылки в данном приложении.

+0

будет проверить это, спасибо! – Anders

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