Повышаем Производительность EF Core с Помощью Скомпилированных Запросов
Скомпилированные запросы в .NET появились как ответ на проблемы с производительностью, возникающие при операциях извлечения данных, особенно в приложениях, использующих ORM, такие как Entity Framework.
До их появления каждая операция извлечения данных требовала от ORM преобразования LINQ в запросы SQL, а этот процесс занимал много времени и ресурсов.
Допустим, у нас есть класс модели данных:
public class User
{
public int Id { get; init; }
public string Name { get; init; }
public int Age { get; init; }
}
Стандартный код для извлечения пользователя по Id будет примерно таким:
using var dbCtx = new AppDbContext();
var user =
dbCtx.Users.FirstOrDefault(x => x.Id == x);
Создадим скомпилированный запрос:
public class AppDbContext
{
private static
Func<AppDbContext, int, User> getUser =
EF.CompileQuery(
(ctx, id) => ctx.User
.FirstOrDefault(n => n.Id == id));
public User GetUser(int id)
{
return getUser(this, id);
}
}
Здесь:
- Статическое поле getUser типа Func<AppDbContext, int, User> - это скомпилированный запрос с использованием метода EF.CompileQuery.
- Метод GetUser – принимает id в качестве параметра и использует статическое поле getUser для получения объекта User из БД.
Мы также можем использовать асинхронный скомпилированный запрос с помощью EF.CompileAsyncQuery. Тогда поле должно быть типа Func<AppDbContext, int, Task<User>>, а метод GetUser будет асинхронным:
public async Task<User> GetUserAsync(int id)
{
return await getUser(this, id);
}
Теперь можно вызвать метод, созданный в нашем контексте:
using var dbCtx = new AppDbContext();
var user = dbCtx.GetUser(id);
Зачем использовать скомпилированные запросы?
1. Производительность
Преобразование запроса из LINQ в SQL выполняется один раз и используется повторно, что особенно полезно для часто выполняемых запросов.
2. Эффективное использование ресурсов
Поскольку запрос компилируется один раз и кэшируется*, это снижает загрузку ЦП и потребление ресурсов, связанных с процессом компиляции запроса.
*Замечание: EF Core автоматически компилирует и кэширует наиболее распространённые запросы, уменьшая необходимость делать это вручную.
Когда не использовать
1. Высокодинамичные запросы
Если запросы часто меняются или динамически конструируются на основе различных условий.
2. Редко выполняемые запросы
Выигрыш в производительности может быть незначительным.
3. Среды с ограниченными ресурсами
Если использование памяти ограничено, будьте осторожны с количеством скомпилированных запросов.
Итого
Скомпилированные запросы в EF Core — мощная функция для оптимизации доступа к БД. Они наиболее полезны для повышения производительности в сценариях с часто повторяющимися запросами. Однако их использование должно быть сбалансировано с учётом потенциальных недостатков, таких как повышенное использование памяти и сложность, особенно в приложениях с динамическими шаблонами запросов или ограниченными ресурсами.
Источник: https://stefandjokic.tech/blog