2010-11-08 74 views
5

我的工作,我們已被告知以下內容的審計跟蹤項目。審計線索:Web應用程序

跟蹤所有的在我們與就像休眠Envers確實影子表數據庫表(200+)。接下來我們爲每個涉及CUD的交易創建快照。

在過去,我實現審計解決方案,爲有限集的每一個我的客戶的重要數據。對於目前的工作,我的問題是:

  1. 是否有意義審計數據庫中的每個表?
  2. 它會像Envers那樣跟蹤數據的價值多少?任何應用程序都希望爲特定數據點提供增量。查詢大量的數據來發現增量似乎是不現實的。
  3. 的Envers像解決方案需要與交易有效排除觸發佔用CUD行動。這是因爲觸發器在自己的事務中運行,因此在應用程序事務回滾的情況下,影子表中的數據可能不同步。我在這裏失蹤的任何東西?
  4. 有人建議使用NoSQL DB進行審計跟蹤嗎?

回答

0

NoSQL數據庫的一個選項是RavenDB,使用其「versioning bundle」。

雖然在這一點上它可能太早了,我最近聽的羊羣代碼,他們talk with Eric Sink on about Veracity一個有趣的小插曲。據我所知,Veracity是部分分佈式版本控制系統,並且是部分NoSQL數據庫。它被設計成從源代碼管理系統到wiki的後端。它已經開發了幾年,但仍然處於預測階段(截至2010年11月)。

+0

爲了準確性,我不確定它是可能的:http://veracity-scm.com/qa/questions/545/how-to-version-database-data -with-veracity – gpasse 2012-01-09 17:55:04

1

完全實現,並且可以更加改善。我希望這可以幫助某人:

public partial class Entity:DbContext 
    { 

     public enum AuditActions {I,U,D} 

     public override int SaveChanges() 
     { 
      ChangeTracker.DetectChanges(); 
      ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext; 
      // string UserName = WindowsIdentity.GetCurrent().Name; 
      IPrincipal principal = Thread.CurrentPrincipal; 
      IIdentity identity = principal == null ? null : principal.Identity; 
      string name = identity == null ? "" : identity.Name; 

      //Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity((userName), roles); 
      List<ObjectStateEntry> objectStateEntryList = 
       ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added 
                 | EntityState.Modified 
                 | EntityState.Deleted) 
       .ToList(); 

      List<DBAudit> AuditList = new List<DBAudit>(); 

      string Audittable = string.Empty; 
      foreach (ObjectStateEntry entry in objectStateEntryList) 
      { 
       Audittable = entry.EntitySet.ToString(); 

       if (!entry.IsRelationship && Audittable!="Audit table name") 
       { 

        //sIsAuditTble =entry.EntitySet="DBAudit"? true:false; 
        switch (entry.State) 
        { 
         case EntityState.Added: 
         AuditList= LogDetails(entry, name, AuditActions.I); 
          break; 
         case EntityState.Deleted: 
         AuditList= LogDetails(entry, name, AuditActions.D); 
          break; 
         case EntityState.Modified: 
         AuditList= LogDetails(entry, name, AuditActions.U); 
          break; 

        } 
       } 
      } 



       using (var context = new ProjectTrackerEntities()) 
       { 
        for (int i = 0; i < AuditList.Count; i++) 
        { 
         context.DBAudits.Add(AuditList[i]); 
         context.SaveChanges(); 
        } 
       } 

      return base.SaveChanges(); 
     } 

     public List<DBAudit> LogDetails(ObjectStateEntry entry, string UserName, AuditActions action) 
     { 
      List<DBAudit> dbAuditList = new List<DBAudit>(); 

     if (action == AuditActions.I) 
      { 

       var keyValues = new Dictionary<string, object>(); 
       var currentValues = entry.CurrentValues; 

      // entry.Entity key = new EntityKey(); 

        DBAudit audit = new DBAudit(); 
        audit.AuditId = Guid.NewGuid().ToString(); 
        audit.RevisionStamp = DateTime.Now; 
        audit.TableName = entry.EntitySet.Name; 
        audit.UserName = UserName; 
        audit.OldData = ""; 
        audit.Actions = action.ToString(); 
        for (int i = 0; i < currentValues.FieldCount; i++) 
        { 
        audit.ChangedColumns = audit.ChangedColumns + currentValues.GetName(i); 
        audit.NewData = audit.NewData + currentValues.GetValue(i); 
        audit.ChangedColumns = audit.ChangedColumns + ", "; 
        audit.NewData = audit.NewData + ", "; 
        } 
        dbAuditList.Add(audit); 
        //LogSave(audit); 




      } 
      else if (action == AuditActions.D) 
      { 
       var keyValues = new Dictionary<string, object>(); 
       var DeletedValues = entry.OriginalValues; 

       // entry.Entity key = new EntityKey(); 


       DBAudit audit = new DBAudit(); 
       audit.AuditId = Guid.NewGuid().ToString(); 
       audit.RevisionStamp = DateTime.Now; 
       audit.TableName = entry.EntitySet.Name; 
       audit.UserName = UserName; 
       audit.NewData = ""; 

       audit.Actions = action.ToString(); 
       for (int i = 0; i < DeletedValues.FieldCount; i++) 
       { 
        audit.ChangedColumns = audit.ChangedColumns + DeletedValues.GetName(i); 
        audit.OldData = audit.OldData + DeletedValues.GetValue(i); 
        audit.ChangedColumns = audit.ChangedColumns + ", "; 
        audit.OldData = audit.OldData + ", "; 
       } 
       dbAuditList.Add(audit); 
      } 
      else 
      { 

        foreach (string propertyName in entry.GetModifiedProperties()) 
        { 
         DBAudit audit = new DBAudit(); 
         DbDataRecord original = entry.OriginalValues; 
         string oldValue = original.GetValue(original.GetOrdinal(propertyName)).ToString(); 

         CurrentValueRecord current = entry.CurrentValues; 
         string newValue = current.GetValue(current.GetOrdinal(propertyName)).ToString(); 

         audit.AuditId = Guid.NewGuid().ToString(); 
         audit.RevisionStamp = DateTime.Now; 
         audit.TableName = entry.EntitySet.Name; 
         audit.UserName = UserName; 
         audit.ChangedColumns = propertyName; 
         audit.OldData = oldValue; 
         audit.NewData = newValue; 
         audit.Actions = action.ToString(); 
         dbAuditList.Add(audit); 
         //LogSave(audit); 


        } 

      } 

     return dbAuditList; 


     } 



    } 
+0

歡迎來到SO,在這裏,解釋爲什麼要使用您的解決方案,而不僅僅是如何,這是一個很好的做法。這會讓你的答案更有價值,並有助於讀者更好地理解你是如何做到的。我還建議你看看我們的FAQ:http://stackoverflow.com/faq。 – ForceMagic 2012-12-19 16:53:30