2011-11-20 25 views
0

我已經創建了以下類,我相信它爲某些需要它的表中的數據行提供了很好的審計功能。這裏是我正在使用的類:添加到Azure表存儲的審計行

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 

} 

任何人都可以在那裏建議我可能會考慮這個類的任何額外的變化。我相信這樣可以,但是因爲我需要爲許多課程實施這個課程,所以我希望聽到有人能夠提出任何更改或補充建議。

回答

4
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 - 本質上,你會創建一個屬性給你想跟蹤的屬性。

另一個缺點是,您會爲審覈日誌消耗大量的存儲空間 - 但您可以有一個後臺進程,根據您的需要定期修剪舊的條目。