Я пытаюсь создать некоторую функциональность, которая сохраняет контрольный след того, как данные в данной пользовательской форме были изменены с течением времени, с датированным аудитом у подножия этой страницы. Например:
02/04/09 21:49 Название изменено с "Tom" на "Chris".
Я делаю это, сохраняя данные в текущем формате в сеансе, а затем сохраняя проверку наличия каких-либо различий в хранящихся данных. Если есть, я храню данные, как это было до последнего редактирования в таблице, называемой историей, и сохраняя новые значения в текущей пользовательской таблице.
Это лучший подход?
Одно предложение; это было бы относительно легко сделать в триггере базы данных. В этом случае вам никогда не придется беспокоиться о том, помнит ли код, запускающий обновление, запись истории.
Я не уверен, что есть один «лучший подход», есть так много переменных, которые нужно учитывать, в том числе, насколько далеко вы продвигаетесь по пути развития.
Пройдя через решения для проверки на основе кода и db-триггера, я привел некоторые комментарии ниже; Надеюсь, вы сможете увидеть, где вы сейчас находитесь (с точки зрения развития), может повлиять на эти проблемы:
Я всегда был поклонником использования одной таблицы, а не разбивки ее на «активную» таблицу и таблицу «истории». Я поместил 4 столбца на эти таблицы, все временные метки: созданы, удалены, запущены, завершены. «созданные» и «удаленные» являются довольно понятными. Временные метки «start» и «end» означают, что запись была фактически «активной» записью. Текущая активная запись будет иметь «начальное» время до момента now()
и NULL
«конец». Разделяя «созданные» и «начальные» времена, вы можете планировать изменения, которые будут иметь место в будущем.
Эта конструкция, в отличие от двухэтажного дизайна, позволяет легко писать запросы, которые будут автоматически работать с нужными данными. Предположим, что ваша таблица хранит налоговую ставку с течением времени … вы не хотите, чтобы все ваши запросы, использующие налоговые ставки в своих расчетах, имели дополнительную сложность в том, чтобы решать, как выглядеть в таблице истории при обработке старых счетов-фактур, для пример … вы можете просто просмотреть ставку налога, действующую на момент составления счета в одном запросе, независимо от того, является ли это текущей налоговой ставкой или нет.
Эта идея изначально не моя (хотя я и сам заново изобрел оригинальную идею, прежде чем читать об этом) … вы можете найти подробное обсуждение этого вопроса в этой онлайн-книге .
Участие в сеансе заставляет меня немного насторожиться (вы уверены, что правильно справляетесь с этим, когда два пользователя работают над одними и теми же данными одновременно?), Но в целом, да, ведение таблицы истории – это правильная вещь.
Я также подумал бы о триггере базы данных для вставки или обновления для записи сведений об изменении (кто, когда, что, значение до, значение после) в отдельную таблицу аудита. Таким образом, вы знаете, что даже если данные будут изменены вне вашего приложения, используя базу данных напрямую, он все равно будет поднят.
Вы также можете сделать что-то, чтобы определить, изменились ли данные вне вашего приложения, например, рассчитать хэш или crc записи и сохранить его в поле где-нибудь, а затем проверить его при чтении данных.
Я думаю, что ваше предложение связано с написанием большого количества кода / метаданных, чтобы обеспечить сопоставление объектов / записей, чтобы вы получали аудит на уровне бизнеса.
В качестве альтернативы триггер базы данных может не дать вам достаточно высокого уровня представления о том, что произошло. Это может быть приемлемым, если вы используете аудит настолько редко, что усилие воссоздания бизнес-значения в порядке.
Это также похоже на хорошее приложение для AOP (Aspects), где вы можете использовать отражение в объектной модели, чтобы сбрасывать что-то значимое, не требуя большого количества метаданных.