2010-11-08 16 views
5

Estoy trabajando en un proyecto de pista de auditoría donde nos han dicho que lo sigamos.Pista de auditoría: aplicación web

Realice un seguimiento de todas las tablas (más de 200) en nuestro db con tablas de sombras al igual que lo hace Hibernate Envers. De esto se desprende que hemos creado una instantánea para cada transacción que involucra a CUD.

En el pasado, implementé soluciones de auditoría para conjuntos finitos de datos importantes para cada uno de mis clientes. Para el presente trabajo, mis preguntas son:

  1. ¿Tiene sentido para auditar cada mesa individual en la base de datos?
  2. ¿Cuánto de valor sería rastrear los datos como lo hace Envers? Cualquier aplicación querría tener deltas para puntos de datos específicos. Consultar grandes conjuntos de datos para descubrir deltas parece ser poco realista.
  3. Una solución tipo Envers requiere que se bloqueen las acciones de CUD con una transacción que descarta de manera efectiva los desencadenantes. Esto se debe a que los desencadenantes se ejecutan en sus propias transacciones y, por lo tanto, los datos en las tablas ocultas pueden desasignarse en caso de que la aplicación revierte las transacciones. ¿Algo que me falta aquí?
  4. ¿Alguien sugiere utilizar DB NoSQL para la pista de auditoría?

Respuesta

0

Una opción para una base de datos NoSQL es RavenDB, usando su "versioning bundle".

Aunque en este punto es probable que sea demasiado temprano, hace poco escuché un episodio interesante del código de Herding donde se talk with Eric Sink on about Veracity. Según tengo entendido, Veracity es parte del sistema de control de versiones distribuidas y parte de la base de datos NoSQL. Está diseñado para ser el back-end de todo, desde un sistema de control de origen hasta un wiki. Ha estado en desarrollo durante un par de años, pero aún está en etapas previas a la beta (a partir de noviembre de 2010).

+0

Para veracidad, no estoy seguro de que es posible: http: //veracity-scm.com/qa/questions/545/how-to-version-database-data -with-veracity – gpasse

1

Totalmente implementado y se puede mejorar más. Espero que esto pueda ayudar a alguien:

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

Bienvenido en SO, aquí, es una buena práctica para explicar por qué utilizar su solución y no solo cómo. Eso hará que su respuesta sea más valiosa y ayudará al lector a tener una mejor comprensión de cómo lo hace. También sugiero que eche un vistazo a nuestras preguntas frecuentes: http://stackoverflow.com/faq. – ForceMagic

Cuestiones relacionadas