Темпоральные таблицы в EF Core. Часть 1
Представьте, что вы создаёте платформу электронной коммерции. Клиент обращается в службу поддержки, утверждая, что его заказ был изменён без его согласия — адрес доставки изменился после оформления. Вашей операционной команде необходимо ответить на следующие вопросы:
- Как выглядел этот заказ на момент его оформления?
- Кто (или какой процесс) изменил адрес доставки и когда?
- Можно ли восстановить предыдущее состояние, не нарушая ссылочную целостность?
Наивный подход — добавить столбцы
CreatedAt, UpdatedAt и ModifiedBy — показывает только дату последнего изменения. Вы не сохраняете историю. Самодельная таблица аудита изменений работает, но требует дисциплины:- каждый разработчик должен помнить о необходимости записи в неё,
- каждый вызов
SaveChanges() должен перехватываться.Темпоральные таблицы SQL Server решают эту проблему на уровне ядра БД, а EF Core 6+ предоставляет к ним доступ через чистый, первоклассный API.
Что это?
Темпоральные таблицы автоматически поддерживают полную историю изменений строк. Ядро БД отслеживает:
- Текущее состояние каждой строки (основная таблица),
- Каждое предыдущее состояние с точным временным диапазоном, в течение которого оно было актуальным (таблица истории).
Два скрытых столбца периода datetime2 — обычно ValidFrom и ValidTo — определяют временной диапазон, в течение которого версия строки была актуальной. Они заполняются и управляются исключительно SQL Server, а не кодом приложения.
При обновлении строки старая версия перемещается в таблицу истории, при этом значение ValidTo устанавливается в текущую метку времени UTC. При удалении строки происходит то же самое — запись остаётся только в таблице истории.
Как это работает
INSERT
- В основную таблицу добавляется новая строка.
- ValidFrom устанавливается в текущее время транзакции.
- ValidTo устанавливается в 9999-12-31 23:59:59.9999999 («всё ещё актуально»).
UPDATE
SQL Server атомарно:
- Копирует текущую строку в таблицу истории, устанавливая значение ValidTo равным времени транзакции.
- Обновляет строку в основной таблице, устанавливая значение ValidFrom равным времени транзакции.
DELETE
- Текущая строка копируется в таблицу истории, устанавливая значение ValidTo равным текущему времени.
- Строка в основной таблице удаляется.
Все метки времени устанавливаются в UTC самим SQL Server. Ваше приложение не может их переопределить. Это фактически функция безопасности — она делает таблицу аудита изменений защищённой от несанкционированного изменения.
Продолжение следует…
Источник: https://thecodeman.net/posts/temporal-tables-efcore-auditing-history