private string _ModifiedBy;
[DisplayName("Modified By")]
public string ModifiedBy
{
get { return _ModifiedBy; }
set { _ModifiedBy = value; Modified = DateTime.Now; }
}
вызовет переполнение стека: установка значения свойства в установщике вызывает установщик, который устанавливает значение свойства, вызывающего установщик и т. Д.
Вы можете установить свойства в конструкторе, но тогда все пойдет не так, если экземпляр сериализуется и десериализуется: когда вы десериализуете его, вызывается открытый конструктор без параметров, и вызывается установщик ..., который устанавливает свойство в дата и время десериализации объекта, а не сохраненное значение.
Лучшим примером может быть создание еще одной таблицы для проверяемых событий. Это может выглядеть примерно так:
public class Audit
{
public string ModifiedBy { get; set; }
public DateTime DateModified { get; set; }
public Type ObjectType { get; set; }
public string Field { get; set; }
public object OldValue { get; set; }
public object NewValue { get; set; }
public static void Record(string user, Type objectType, object oldValue, object newValue)
{
Audit newEvent = new Audit
{
ModifiedBy = user,
DateModified = DateTime.UtcNow, // UtcNow avoids timezone issues
ObjectType = objectType,
OldValue = oldValue,
NewValue = newValue
};
Save(newEvent); // implement according to your particular storage classes
}
}
Затем, когда вы вносите изменения в объект, который хотите проверить, вызывайте Audit.Record()
примерно так:
public class SomeKindOfAuditableEntity
{
private string _importantFieldToTrack;
public string ImportantFieldToTrack
{
get { return _importantFieldToTrack; }
set
{
Audit.Record(GetCurrentUser(), this.GetType(), _importantFieldToTrack, value);
_importantFieldToTrack = value;
}
}
}
Таким образом, вы сохраняете журнал всех изменений, которые происходят со всеми "интересными" свойствами ваших таблиц. Это имеет несколько других преимуществ:
- вы видите старые и новые значения каждого изменения
- журнал аудита хранится в другом месте, чем сами данные, разделяя проблемы
- вам не нужно иметь базовый класс для ваших классов данных
- аудит старых изменений ведется, поэтому вы можете просмотреть весь журнал изменений объекта
Основным недостатком является то, что вам необходимо добавлять код в каждый установщик для каждого интересующего вас свойства. Есть способы смягчить это с помощью атрибутов и отражений и аспектно-ориентированного программирования - см., Например, реализацию Spring здесь: http://www.springframework.net/doc-latest/reference/html/aop.html - по сути, вы бы создали атрибут для свойств, которые вы хотите отслеживать.
Другим недостатком является то, что вы будете использовать много памяти для журнала аудита, но у вас может быть фоновый процесс, который периодически удаляет старые записи по своему усмотрению.