2010-11-08 21 views
5

Sto lavorando a un progetto di audit trail in cui ci è stato detto di seguire.Percorso di controllo: applicazione Web

Tieni traccia di tutti i tavoli (oltre 200) nel nostro database con tabelle shadow proprio come fa Hibernate Envers. Ne consegue che abbiamo creato uno snapshot per ogni transazione che coinvolge CUD.

In passato, ho implementato soluzioni di controllo per serie limitate di dati importanti per ciascuno dei miei clienti. Per il lavoro corrente, le mie domande sono:

  1. Ha senso controllare ogni singola tabella nel database?
  2. Quanto di valore sarebbe traccia dei dati come fa Envers? Qualsiasi applicazione vorrebbe avere delta per punti dati specifici. Interrogare enormi serie di dati per capire i delta sembra non realistico.
  3. Una soluzione simile a Envers richiede il vincolamento delle azioni CUD con una transazione che esclude efficacemente i trigger. Questo perché i trigger vengono eseguiti nelle proprie transazioni e quindi i dati nelle tabelle shadow possono andare fuori sincrono in caso di rollback delle transazioni dall'applicazione. Qualcosa che mi manca qui?
  4. Qualcuno suggerisce di utilizzare DB NoSQL per l'audit trail?

risposta

0

Un'opzione per un database NoSQL è RavenDB, utilizzando il suo "versioning bundle".

Anche se a questo punto è probabilmente troppo presto, ho recentemente ascoltato un episodio interessante del codice Herding in cui sono talk with Eric Sink on about Veracity. Come ho capito, Veracity è un sistema di controllo delle versioni distribuito in parte e un database NoSQL parziale. È progettato per essere il back-end di qualsiasi cosa, da un sistema di controllo sorgente a un wiki. È in sviluppo da un paio d'anni, ma è ancora efficacemente nelle fasi pre-beta (dal novembre 2010).

+0

Per veridicità, non sono sicuro che sia possibile: http: //veracity-scm.com/qa/questions/545/how-to-version-database-data -with-veracity – gpasse

1

Completamente implementato e può essere migliorato di più. Spero che questo possa aiutare qualcuno:

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

Benvenuti su SO, qui è una buona pratica spiegare perché utilizzare la soluzione e non solo come. Ciò renderà la tua risposta più preziosa e aiuterà ulteriormente il lettore ad avere una migliore comprensione di come lo fai. Suggerisco anche di dare un'occhiata alle nostre FAQ: http://stackoverflow.com/faq. – ForceMagic

Problemi correlati