TGStat
TGStat
Qidiruv uchun matnni kiriting
Ilg‘or kanal qidiruvi
  • flag Uzbek
    Sayt tili
    flag Russian flag English flag Uzbek
  • Saytga kirish
  • Katalog
    Kanal va guruhlar katalogi Hududiy to‘plamlar Tematik to‘plamlar Платные каналы Kanallar qidiruvi
    Kanal/guruh qo‘shish
  • Reytinglar
    Kanallar reytingi Guruhlar reytingi Postlar reytingi
    Brendlar va shaxslar reytingi
  • Analitika
  • Postlarda qidiruv
  • Telegram'ni kuzatish
  • Targ‘ibot
    Yandex Business orqali reklama TGStat Agency orqali kanallarda reklama TGStat.ru saytida reklama
.NET sh blog

22 Feb 2025, 12:32

Telegram'da ochish Ulashish Shikoyat qilish

EntityFrameworkCore потрясающий инструмент который сильно упрощает нам жизнь, но если не контролировать какие SQL запросы уходят в СУБД, то это может доставить боль при обновлениях мажорных версий, т.к. EF может в целом изменить подходы к построению SQL и что-нибудь сломать или сильно замедлить запросы из-за генерации неэффективных запросов.

А такое случается достаточно часто, несмотря даже на сумасшедшие 286 882 тестов, которые к сожалению всё равно не могут покрыть всевозможные сценарии и так или иначе будут просачиваться баги.

К примеру, несколько лет назад на одном проекте при апдейте с версии 2.2 на 3.0, у меня один запрос стал тянуть чуть ли не все данные из СУБД, из-за чего ему стало не хватать work_mem, поэтому он начал активно использовать диск и генерировал временные файлы. Но запрос выполнялся долго, отменялся по таймауту, но почему-то не подчищалась папка temp и таким образом диск быстро заполнялся и пришлось ребутать СУБД чтобы он не ушел в режим readonly.
Решилось всё переписыванием запроса с учетом особенностей уже версии 3.0.

Тогда же занесли еще один досадный баг, когда просто забыли рекурсивно пройтись по деревьям выражений из-за чего сломалось использование PredicateBuilder, а сам фикс был однострочным, но помню много времени ждал пока этот фикс доедет до релиза.
А из свежих, в 9 версии сломали GroupBy в некоторых кейсах.

Подобные проблемы регулярно встречаются и хорошо бы это покрыть тестами и недопустить проблемы до прода.

Самый простой способ тестирования генератора SQL запросов - это snapshot тесты.
В .NET есть крутая библиотека Verify и Verify.EntityFramework.
Используя его, мы можем встроиться в DbContext и с помощью интерцепторов записывать все исходящие SQL запросы и сохранить их как снепшот.
При апдейте версии EFCore или при изменении нашего кода, такие тесты покажут изменения в SQL запросах если они были.

Полноценного примера в доке нет, поэтому держите гайд:

1. В Composition Root (в проекте со Startup.cs или Program.cs) добавить зависимость от Verify.EntityFramework и вызвать метод расширения EnableRecording на DbContextOptionsBuilder. Его надо добавить только при запуске тестов:
builder.Services.AddDbContext((sp, options) =>
{
// тут настройка DbContext: options.UseNpgsql и т.п.

// при запуске интеграционных тестов окружение проставляю в IntegrationTests.
if (_env.EnvironmentName == "IntegrationTests" && options is DbContextOptionsBuilder o)
{
o.EnableRecording();
}
}

2. В сборке с интеграционными тестами подключить библиотеку Verify.NUnit/XUnit и инициализировать Verify.EntityFramework:
public static class ConfigureVerify
{
[ModuleInitializer]
public static void Init()
{
var model = GetDbModel();
VerifyEntityFramework.Initialize(model);
}

private static IModel GetDbModel()
{
var options = new DbContextOptionsBuilder();
options
.UseNpgsql("fake")
.UseSnakeCaseNamingConvention();
using var data = new ApplicationDbContext(options.Options);
return data.Model;
}
}

3. В тестах обернуть в using вызов тестируемого кода (всю секцию act)
using (Recording.Start())
{
// act
await sut.ExecuteAsync();
}

и вызывать Verify в качестве assert:
await Verify().AutoVerify(includeBuildServer: false);

После успешного прохода теста, появится *.verified.txt файл, в котором будут все отправленные SQL запросы в рамках тестируемого сценария:
{
ef: [
{
Type: ReaderExecutedAsync,
HasTransaction: true,
Text:
-- StrictOrderingOutboxRepository:LockAndReturnItemsBatchAsync

SELECT * FROM kafka_ef_outbox_items

ORDER BY id ASC
LIMIT 10
FOR UPDATE NOWAIT;
},
]
}
Если изменить код, добавить еще SQL вызовы или поменять их местами, то изменится и снепшот, который можно будет провалидировать и закоммитить в git репозиторий.
Если изменится SQL запрос, можно всегда его отсюда скопировать и сделать explain, посмотреть на план запроса и либо переписать либо оставить как есть.

566 0 10 1 23
Katalog
Kanal va guruhlar katalogi Kanallar to‘plamlari Kanallar qidiruvi Kanal/guruh qo‘shish
Reytinglar
Telegram-kanallar reytingi Telegram-guruhlar reytingi Postlar reytingi Brendlar va shaxslar reytingi
API
Statistika API'si Postlar qidiruvi API'si API Callback
Kanallarimiz
@TGStat @TGStat_Chat @telepulse @TGStatAPI
O‘qish
Академия TGStat Telegram tadqiqoti 2019 Telegram tadqiqoti 2021 Telegram tadqiqoti 2023
Kontaktlar
Справочный центр Qo‘llab-quvvatlash Email Vakansiyalar
Har xil narsalar
Foydalanuvchi shartnomasi Maxfiylik siyosati Ommaviy oferta
Botlarimiz
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot