Как настроить запрос Entity Framework - PullRequest
2 голосов
/ 04 марта 2020

Я недавно обновил EF Core 2.2.6 до 3.1 и столкнулся с множеством проблем снижения производительности.

У меня есть запрос ниже, кто-то может мне помочь с тем, как я могу оптимизировать этот запрос, чтобы значения загружаются намного быстрее.

var valuations = await _context.Valuation
                               .Where(a => a.PortfolioCompany.DealCode == dealCode && 
                                           a.ValuationPeriod.PeriodName == periodName)
                               .Include(a => a.ValuationPeriod)
                               .Include(x => x.ValuationState)
                               .Include(x => x.PortfolioCompany)
                               .ThenInclude(up => up.UserPermission)
                               .FirstOrDefaultAsync(cancellationToken);

_context.Entry(valuations).Collection(a => a.ValuationFundTemplate).Load();
_context.Entry(valuations)
        .Collection(a => a.UserValuationAssignments).Query()
        .Include(u => u.User).Load();

return valuations;

При большом количестве включений производительность падает. Пожалуйста, помогите мне с этим.

Включения, которые вы видите здесь, не являются коллекциями:

public virtual ValuationPeriod ValuationPeriod { get; set; }

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

Я предлагаю вам проверить, что sql медленно. (как вы описали, это первый?)

EF3 имеет изменения, которые могут вызвать проблему:

Внимание

Начиная с версии 3.0.0, каждый Включить приведет к добавлению дополнительного JOIN к SQL запросам, созданным реляционными провайдерами, тогда как предыдущие версии генерировали дополнительные SQL запросы. Это может значительно изменить производительность ваших запросов, в лучшую или худшую сторону. В частности, запросы LINQ с чрезвычайно большим числом операторов включения могут быть разбиты на несколько отдельных запросов LINQ, чтобы избежать проблемы декартового взрыва.

Обычно я предпочитаю выбирать только необходимые данные с помощью Select для помещения результата в dto, отличное от сущностей db.

Другой момент может заключаться в проверке сгенерированного плана выполнения sql, чтобы увидеть, что такое шея bottle.

0 голосов
/ 05 марта 2020

Шаблон (ы) фонда и присвоения оценки пользователей должны быть включены в запрос, а не загружены впоследствии. Если эти оценки возвращаются, куда / куда они возвращаются? Это метод контроллера MVC, возвращающий эти объекты в представление? или сервис, возвращающий этот граф сущностей, чтобы можно было запрашивать и / или обновлять детали?

var valuations = await _context.Valuation
                           .Where(a => a.PortfolioCompany.DealCode == dealCode && 
                                       a.ValuationPeriod.PeriodName == periodName)
                           .Include(a => a.ValuationPeriod)
                           .Include(x => x.ValuationState)
                           .Include(x => x.PortfolioCompany)
                           .ThenInclude(up => up.UserPermission)
                           .Include(x => x.ValuationFundTemplate)
                           .Include(x => x.UserValuationAssignments)
                           .ThenInclude(a => a.User)
                           .FirstOrDefaultAsync(cancellationToken);

Запустите приведенный выше или исходный оператор, если в указанном выше чего-то не хватает, используя EF Core 2.2.6 и Core 3.1 с Profiler, работающим с вашей базой данных. Например, для SQL Server SSMS (студия управления) имеет встроенный профилировщик, или вы можете использовать более легкий, например, Express Profiler. Он помогает работать с изолированным экземпляром базы данных, таким как локальная база данных или тестовая реплика, с которой работает только ваш тестовый экземпляр, поэтому вам не придется просеивать шум других запросов, выполняемых из тестовых сред или других разработчиков. Установите точку останова, а затем выполните запрос. Запишите SQL и время выполнения, затем позвольте коду завершиться. Был ли это единственный запущенный запрос или, например, когда вызывающий метод завершился, выполнялись ли дополнительные запросы? (Т.е. дополнительные ленивые вызовы загрузки)

Сравните SQL и производительность между 2.2.6 и 3.1, чтобы найти подсказки о том, что произошло. Недавно я видел случаи, когда Core 2.2.6 компилирует запросы совершенно иначе, чем Core 3.1, так что это может быть серьезное изменение или ошибка в 3.1. (Единственная уверенность при разработке на переднем крае - это то, что вы получите кровавый эффект:)

Если это метод контроллера или тому подобное, возвращающий данные в представление, рассмотрите возможность использования Select или Automapper's. ProjectTo для загрузки данных из графа сущностей в структуру модели представления, подходящую для представления. Это исключает необходимость использования Include для увеличения нагрузки или проблем с производительностью при отложенных вызовах загрузки, отключенных при сериализации. Он также генерирует более эффективные запросы и сокращает объем данных, передаваемых по проводам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...