审计添加到Azure表存储的行

本文关键字:存储 Azure 添加 审计 | 更新日期: 2023-09-27 18:15:24

我已经创建了下面的类,我认为它为需要它的某些表中的数据行提供了一些很好的审计功能。下面是我使用的类:

public class AuditableTableServiceEntity : TableServiceEntity  
{
    protected AuditableTableServiceEntity()
        : base()
    {
    }
    protected AuditableTableServiceEntity(string pk, string rk)
        : base(pk, rk) 
    { 
    }
    #region CreatedBy and ModifiedBy
    private string _CreatedBy;
    [DisplayName("Created By")]
    public string CreatedBy
    {
        get { return _CreatedBy; }
        set { _CreatedBy = value; Created = DateTime.Now; }
    }
    [DisplayName("Created")]
    public DateTime? Created { get; set; }
    private string _ModifiedBy;
    [DisplayName("Modified By")]
    public string ModifiedBy
    {
        get { return _ModifiedBy; }
        set { _ModifiedBy = value; Modified = DateTime.Now; }
    }
    [DisplayName("Modified")]
    public DateTime? Modified { get; set; }
    #endregion
}

有谁能建议我对这门课做任何额外的改变吗?我相信这是可以的,但因为我需要实现这许多类,我想听到如果有人可以建议任何更改或添加。

审计添加到Azure表存储的行

private string _ModifiedBy;
[DisplayName("Modified By")]
public string ModifiedBy
{
    get { return _ModifiedBy; }
    set { _ModifiedBy = value; Modified = DateTime.Now; }
}

将导致堆栈溢出:在setter中设置属性的值调用setter,后者设置该属性的值,后者调用setter,依此类推。

你可以在构造函数中设置属性,但是如果一个实例被序列化和反序列化,事情就会中断:当你反序列化它时,调用公共无参数构造函数,调用setter…它将属性设置为对象反序列化的日期和时间,而不是存储值。


更好的模式可能是为可审计事件创建另一个表。这可能看起来像这样:

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;
        }
    }
}

这样你就存储了一个日志,记录了发生在你的表中所有"有趣的"属性上的所有变化。这还有其他一些优点:

  • 你可以看到每次变化的新旧值
  • 审计日志与数据本身存储在不同的位置,分离关注点
  • 你不需要为你的数据类创建基类
  • 对旧更改的审计保留在周围,因此您可以返回到对象更改的整个日志

主要缺点是您需要为您感兴趣的每个属性的每个setter添加代码。有一些方法可以通过属性、反射和面向方面的编程来缓解这个问题——例如,请参见这里的Spring实现:http://www.springframework.net/doc-latest/reference/html/aop.html——本质上,您可以为想要跟踪的属性创建一个属性。

另一个缺点是您将为审计日志消耗大量存储空间—但是您可以有一个后台进程,在您认为合适的时候定期删除旧条目。