TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3220 1.7K
День 2690. #ЗаметкиНаПолях
Темпоральные таблицы в EF Core. Часть 5

1. Что это?
2. Настройка
3. Запросы
4. Добавление версионирования и производительность
 
Распространенные ошибки и способы их избежать

Ошибка 1: Скафолдинг темпоральных таблиц при обратном проектировании
Если вы используете шаблон dotnet ef dbcontext для существующей темпоральной БД, EF Core может некорректно определить конфигурацию таблиц. Всегда проверяйте созданный шаблон DbContext и добавляйте конфигурацию IsTemporal() вручную, если это необходимо.
 
Ошибка 2: Мягкое удаление и темпоральные таблицы
Если ваша сущность использует паттерн мягкого удаления (флаг IsDeleted), темпоральные таблицы будут отслеживать изменения этих флагов. Т.е. «удалённые» строки по-прежнему будут находиться в основной таблице, просто с IsDeleted = true — и каждый раз, когда кто-то запрашивает историю, ему нужно будет это учитывать. Подумайте, нужны ли вам оба механизма, или достаточно жёсткого удаления и темпоральных таблиц для соответствия вашим требованиям.
 
Ошибка 3: Массовые операции в обход EF Core
Это позволяет обойти отслеживание изменений EF Core, но при этом работает с темпоральными таблицами, поскольку они задаются на уровне SQL Server:
await _db.Database.ExecuteSqlRawAsync(
 "UPDATE Orders SET Status = 'Archived' WHERE CreatedAt < {0}",
 DateTime.UtcNow.AddYears(-1));

Если вы используете стороннюю библиотеку для пакетной обработки запросов, которая напрямую вызывает SqlBulkCopy, имейте в виду, что она обходит триггеры, но НЕ темпоральные таблицы — они обрабатываются на уровне движка.
 
Ошибка 4: Миграции EF Core на темпоральные таблицы требуют осторожности
При добавлении нового столбца в темпоральную таблицу EF Core также должен добавить его в таблицу истории. EF Core обрабатывает это автоматически в миграциях, но если вы когда-либо вручную изменяли таблицу истории, миграция завершится неудачей. Никогда не изменяйте схему таблицы истории напрямую.
 
Ошибка 5: Забывание о UTC
Временные метки в таблицах всегда в формате UTC. Если ваше приложение использует местное время, преобразования могут вызвать трудно отслеживаемые ошибки в запросах к историческим данным:
// ❌ Используется местное время
var asOf = DateTime.Now.AddDays(-1);
 
// ✅ Всегда используйте UTC
var asOf = DateTime.UtcNow.AddDays(-1);
 
var snapshot = await _db.Orders
  .TemporalAsOf(asOf)
  .FirstOrDefaultAsync(o => o.Id == orderId);

 
Когда НЕ следует использовать темпоральные таблицы
- Таблицы с высокой частотой записи (например, телеметрия в реальном времени, состояние сессии)
Накладные расходы на запись и рост истории будут проблемой. Вместо этого используйте выделенную БД временных рядов или хранилище событий.
 
- Конфиденциальность персональных данных/GDPR
Темпоральные таблицы затрудняют удаление данных — таблица истории сохраняет старые версии. Если вам необходимо поддерживать запросы «права на забвение», вам потребуется реализовать процесс удаления вручную, который отключает версионирование, очищает историю и снова включает его.
 
- Таблицы с BLOB-объектами или большими столбцами NVARCHAR(MAX)
Каждое обновление копирует всю строку в историю, включая большие поля. Это может привести к чрезвычайно быстрому росту таблицы истории.

- Требования к согласованности между базами данных
Временные метки являются индивидуальными для каждой БД. Если бизнес-транзакция охватывает несколько БД, временные записи будут иметь немного разные метки времени, что делает восстановление данных на определённый момент времени между базами данных ненадёжным.
 
Источник:
https://thecodeman.net/posts/temporal-tables-efcore-auditing-history
  • 👎 1
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →