Сначала вам нужно добавить набор свойств в ваши таблицы:
- Версия - время последней модификации (также может быть счетчик автоинкремента вместо времени).
- LastModifiedBy - ссылка на пользователя, который произвел последнее изменение (если вы его сохранили).
Тогда у вас есть несколько вариантов хранения истории версий. Вы можете
Создайте новую таблицу для каждой из основных таблиц, для которых вы хотите сохранить историю. В этих таблицах истории будут все те же поля, что и в основной таблице, но первичные и внешние ключи не будут применены. Для каждого внешнего ключа также сохраните Версию ссылочной записи на момент создания версии.
ИЛИ вы можете сериализовать все интересное о вашей сущности и хранить все эти сериализованные большие двоичные объекты для всех сущностей, которые вы хотите создать в одной версии, в одной таблице глобальной истории (лично я предпочитаю первый подход).
Как вы заполняете свои таблицы истории? Через обновление и удаление триггеров.
- В триггере обновления для вашей сущности - скопируйте все предыдущие значения в таблицу истории. Для каждого внешнего ключа - также скопируйте текущую версию ссылочной сущности.
- В триггере удаления - в основном то же самое.
Обратите внимание, что все больше и больше современных систем на самом деле ничего не удаляют. Они просто помечают вещи как удаленные. Если вы хотите следовать этому шаблону (который имеет несколько преимуществ) - вместо удаления добавьте флаг IsDeleted для ваших сущностей (разумеется, тогда вам придется отфильтровывать удаленные сущности повсюду).
Как вы смотрите свою историю? Просто используйте таблицу истории, так как она имеет все те же свойства, что и основная таблица - не должно быть проблемой. Но - при расширении внешних ключей - убедитесь, что версия объекта, на которую указывает ссылка, такая же, как вы храните в своей таблице истории. Если это не так - вам нужно перейти в таблицу History этой сущности, на которую ссылаются, и получить значения там. Таким образом, у вас всегда будет снимок того, как выглядит объект в тот момент, включая все ссылки.
В дополнение ко всему вышесказанному - вы также можете восстановить состояние вашей сущности до любой предыдущей версии.
Обратите внимание, что эта реализация, хотя и проста, может занимать некоторое пространство, потому что она хранит снимок , а не только вносимые изменения. Если вы хотите просто сохранить изменения - в триггере обновления вы можете обнаружить, какие поля были изменены, сериализовать их и сохранить в глобальной таблице истории. Таким образом, вы можете по крайней мере показать в пользовательском интерфейсе, что было изменено и кем (хотя у вас могут быть проблемы с возвратом к какой-либо предыдущей версии).