Ответ 1
Почему Равным называется 50M раз?
Звучит довольно подозрительно. У вас есть 10.000 отзывов и 50.000.000 звонков на Equals
. Предположим, что это вызвано отображением идентичности, внутренне реализованным EF. Карта идентичности гарантирует, что каждый объект с уникальным ключом отслеживается контекстом только один раз, поэтому, если контекст уже имеет экземпляр с тем же ключом, что и загруженная запись из базы данных, он не будет реализовывать новый экземпляр и вместо этого использует существующий. Теперь, как это может совпадать с этими числами? Мое страшное предположение:
=============================================
1st record read | 0 comparisons
2nd record read | 1 comparison
3rd record read | 2 comparisons
...
10.000th record read | 9.999 comparisons
Это означает, что каждая новая запись сравнивается с каждой существующей записью в карте идентификации. Применяя математику для вычисления суммы всех сравнений, мы можем использовать нечто, называемое "Арифметическая последовательность":
a(n) = a(n-1) + 1
Sum(n) = (n / 2) * (a(1) + a(n))
Sum(10.000) = 5.000 * (0 + 9.999) => 5.000 * 10.000 = 50.000.000
Надеюсь, я не ошибся в своих предположениях или расчетах. Подождите! Надеюсь, я ошибся, потому что это не кажется хорошим.
Попробуйте отключить отслеживание изменений = надежно отключить проверку идентификационной карты.
Это может быть сложно. Начните с:
var bookAndReviews = db.Books.Where(b => b.BookId == id)
.Include(b => b.Reviews)
.AsNoTracking()
.FirstOrDefault();
Но есть большая вероятность, что ваше свойство навигации не будет заполнено (потому что оно обрабатывается отслеживанием изменений). В этом случае используйте этот подход:
var book = db.Books.Where(b => b.BookId == id).AsNoTracking().FirstOrDefault();
book.Reviews = db.Reviews.Where(r => r.BookId == id).AsNoTracking().ToList();
В любом случае вы можете увидеть, какой тип объекта передается в Equals? Я думаю, что это должно сравнивать только первичные ключи, и даже 50M целочисленные сравнения не должны быть такой проблемой.
Как побочная заметка EF медленная - это хорошо известный факт. Он также использует отражение внутри, когда материализует объекты, поэтому просто 10.000 записей могут занимать "некоторое время". Если вы этого не сделали, вы также можете отключить создание динамического прокси (db.Configuration.ProxyCreationEnabled
).