Audit trail: Web application
Fully implemented and can be improved more. I hope this may help someone :
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; } }
One option for a NoSQL database is RavenDB, using its "versioning bundle".
Though at this point it's probably too early, I recently listened to an interesting episode of Herding code where they talk with Eric Sink on about Veracity. As I understand, Veracity is part distributed version control system, and part NoSQL database. It is designed to be the backend to anything from a source control system to a wiki. It's been in development for a couple years, but is still effectively in pre-beta stages (as of Nov 2010).