Почему Equals называется 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
).