Подтвердить что ты не робот

Ошибка DbContext Query в сравнении с ObjectContext

Недавно я перенес мою модель объекта из ObjectContext, используя 4.1 в DbContext, используя 5.0. Я начинаю сожалеть об этом, потому что замечаю очень низкую производительность по запросу, используя DbContext vs ObjectContext. Здесь тестовый сценарий:

Оба контекста используют одну и ту же базу данных с примерно 600 таблицами. LazyLoading и ProxyCreation отключены для обоих (не показаны в примере кода). Оба имеют предварительно сгенерированные представления.

Тест сначала делает 1 вызов для загрузки рабочего пространства метаданных. Затем в цикле for, который выполняется 100 раз, я обновляю контекст и делаю один вызов, который принимает первый 10. (Я создаю контекст внутри цикла for, потому что это имитирует использование в службе WCF, что создаст контекст каждый раз)

for (int i = 0; i < 100; i++)
{
    using (MyEntities db = new MyEntities())
    {
        var a = db.MyObject.Take(10).ToList();
    } 
} 

Когда я запускаю это с ObjectContext, он занимает около 4,5 секунд. Когда я запускаю его с помощью DbContext, это занимает около 17 секунд. Я профилировал это с использованием профилировщика производительности RedGate. Для DbContext кажется, что основным виновником является метод UpdateEntitySetMappings. Это вызывается для каждого запроса и, как представляется, извлекает метаданные и просматривает каждый элемент в OSpace. AsNoTracking не помогло.

EDIT: Чтобы дать более подробную информацию, проблема связана с созданием\инициализацией DbSet и ObjectSet, а не с фактическим запросом. Когда я делаю вызов с ObjectContext, для создания ObjectSet требуется в среднем 42 мс. Когда я звоню с DbContext, для создания внутреннего dbset требуется около 140 мс. Оба объекта ObjectSet и DbSet выполняют некоторые сопоставления сопоставления сущностей из метаданных. Я заметил, что DbSet делает это для ВСЕХ типов в рабочей области, а ObjectSet - нет. Я предполагаю (не пробовал), что модель с меньшим количеством таблиц отличается от разницы в производительности.

4b9b3361

Ответ 1

Меня также беспокоит недооценка первого подхода к коду, и я выполнил некоторые тесты в сценарии, аналогичном вашему

http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html

Результаты не были сюрпризом, поскольку DbContext является оберткой над ObjectContext, он должен пожертвовать производительностью для простоты. Однако мои тесты показывают, что:

  • Чем больше записей вы получите, тем меньше разница.
  • чем больше записей вы получите, тем более важно отключить отслеживание, если вы хотите быть быстрее

Например, извлечение всего 10 записей

enter image description here

Обратите внимание, что код сначала значительно медленнее, чем первая модель, и нет заметной разницы между отслеживанием и отсутствием отслеживания - оба наблюдения в точности совпадают с вашими.

Однако при извлечении 10000 строк у вас есть

enter image description here

Обратите внимание, что почти нет разницы между первым кодом и моделью в версии notracking. Кроме того, оба они работают на удивление хорошо, почти так же быстро, как исходный datareader ado.net.

Пожалуйста, следуйте за моей записью в блоге для более подробной информации.

Этот простой тест помог мне сначала принять природу кода. Я по-прежнему предпочитаю его для небольших проектов из-за двух особенностей: poco-сущностей и миграций. С другой стороны, я бы никогда не выбрал ни одного из них для проекта, где производительность является критическим требованием. Это фактически означает, что я, вероятно, никогда больше не буду использовать первый подход к модели.

(Замечание: мой тест также показывает, что с nHibernate что-то не так. Я все еще не нашел никого, кто мог бы мне объяснить это, хотя я консультировался с двумя независимыми разработчиками, которые ежедневно используют NH)

Ответ 2

DbContext - это оболочка для ObjectContext. Вот хороший ответ о вашем вопросе. Возможно, что для облегчения использования они пожертвовали производительностью.

Ответ 3

Я использую Simple.Data для запроса миллионов записей, и он работает довольно хорошо и быстро.