Вопрос

Я рассматривал некоторые способы аудита с помощью Entity Framework.Многие из них показывают сравнение старых и новых значений.Это отлично подходит для контрольного журнала, но я хочу делать снимки объектов.

Например...Допустим, у меня есть приложение, которое управляет продуктами.Продукт имеет несколько атрибутов и связанных с ним других объектов.Допустим, я меняю объект 10 раз.Допустим также, что важно, чтобы я мог просматривать экраны этих изменений объекта (не контрольный журнал, а то, как на самом деле выглядел экран в формате только для чтения).Что меня интересует, так это возможность получить исходный объект продукта EF (со всеми связанными данными) для всех 10 этих изменений (в зависимости от того, что я хочу увидеть) и использовать его для привязки к моему экрану.

Если я использую SQL Server, какой тип сериализованного объекта мне следует использовать в настоящее время (XML, blob и т. д.)?Есть ли смысл это делать?

Это было полезно?

Решение

Давайте посмотрим.Вам необходимо взять граф объекта и сериализовать его в базу данных в формате, который позволит вам материализовать его позже.Я думаю, что есть инструменты, которые делают именно это.Один из них, как мне кажется, — это Entity Framework.

То, что вы хотите сделать, — это очень распространенная вещь.Рассмотрим вики-движок.Вики должна иметь предварительную версию, которую все видят, а также предыдущие версии каждого документа.Вики также должна иметь возможность отображать предыдущую ревизию точно так же, как отображается редакция кончика.Поэтому для них обоих следует использовать один и тот же формат хранения.

Я бы предложил вам разрешить версионирование всех типов сущностей.При редактировании типа объекта вы редактируете начальную версию и сохраняете предыдущую версию, содержащую предыдущие значения.(Причина, по которой вы редактируете версию подсказки вместо вставки новой подсказки, заключается в том, что другие объекты, которые в настоящее время не материализованы в ObjectContext, могут содержать ссылки на подсказку, которые вы хотели бы сохранить как ссылки на подсказку, а не ссылки на задняя ревизия.)

При необходимости вы можете секционировать таблицы SQL Server, чтобы предыдущие версии хранились в другой группе файлов.Это позволит вам отдельно создавать резервные копии версий наконечника и предыдущих версий.

Другие советы

Сначала вам нужно добавить в ваши таблицы набор свойств:

  • Версия - время последней модификации (вместо времени также может быть автоинкрементный счетчик).
  • LastModifiedBy — ссылка на пользователя, внесшего последнее изменение (если вы его сохранили).

Тогда у вас есть несколько вариантов хранения истории версий.Ты можешь

  1. Создайте новую таблицу для каждой из основных таблиц, историю которых вы хотите сохранить.Эти таблицы истории будут иметь все те же поля, что и основная таблица, но первичные и внешние ключи не будут применяться.Для каждого внешнего ключа также сохраните версию ссылочной записи на момент создания версии.

  2. ИЛИ вы можете сериализовать все, что интересно о вашей сущности, и хранить все эти сериализованные BLOB-объекты для всех сущностей, которые вы хотите версионировать, в одной глобальной таблице истории (лично я предпочитаю первый подход).

Как вы заполняете свои таблицы истории?Через триггеры обновления и удаления.

  • В триггере обновления для вашей сущности скопируйте все предыдущие значения в таблицу истории.Для каждого внешнего ключа также скопируйте текущую версию объекта, на который ссылаются.
  • В триггере удаления - в основном делайте то же самое.

Обратите внимание, что все больше и больше современных систем на самом деле ничего не удаляют.Они просто отметка вещи как удаленные.Если вы хотите следовать этому шаблону (который имеет несколько преимуществ) — вместо удаления добавьте флаг IsDeleted к вашим объектам (конечно, вам придется везде фильтровать удаленные объекты).

Как вы смотрите на свою историю?Просто используйте таблицу истории, поскольку она имеет все те же свойства, что и основная таблица, и это не должно быть проблемой.Но при расширении внешних ключей убедитесь, что версия ссылочного объекта совпадает с той, которую вы храните в своей таблице истории.Если это не так, вам нужно перейти в таблицу истории этого объекта, на который ссылаются, и получить там значения.Таким образом, у вас всегда будет снимок того, как объект выглядел в ЭТОТ момент, включая все ссылки.

В дополнение ко всему вышесказанному — вы также можете восстановить состояние вашей сущности до любой предыдущей версии.

Обратите внимание, что эта реализация, хотя и проста, может занимать некоторое пространство, поскольку она хранит снимок, происходят не только изменения.Если вы хотите просто сохранить изменения - в триггере обновления вы можете определить, какие поля были изменены, сериализовать их и сохранить в таблице глобальной истории.Таким образом, вы сможете, по крайней мере, показать в пользовательском интерфейсе, что и кем было изменено (хотя у вас могут возникнуть проблемы с возвратом к какой-либо предыдущей версии).

В проекте, который я недавно создал, мы использовали подключение к SaveChanges метод в DbContext сорт.Это дало нам доступ к экземпляру ChangeTracker сорт.Вызов ChangeTracker.Entries() дает вам доступ к списку DbEntityEntry. DbEntityEntry имеет следующие интересные свойства и методы:

  • State - является ли объект вновь созданным, измененным или удаляемым
  • Entity - копия объекта в его нынешнем виде
  • CurrentValues - перечисление отредактированных значений
  • OriginalValues - перечисление исходных значений

Мы создали набор POCO для наборов изменений и изменений, к которым затем можно было получить доступ через EF.Это позволило нашим пользователям просматривать изменения на уровне полей, а также даты и ответственных пользователей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top