S. Lacy
S. Lacy

Reputation: 51

Better Way to Create an Audit Trail Using Entity Framework

I have looked through many examples of creating an audit trail using the Entity Framework and have yet to find anything that works for me. There must be a slick/terse way to do it by simply overriding SaveChanges in the DB Context and using the ChangeTracker...issues I have run into are things such as when adding (creating) an entity it does not have an ID until after you save it and when you save it, it seems to blast what's in the change tracker. Anyway, I have got an audit trail working but it's ugly as hell and I was looking for help in simplifying this and making it such that I don't have to add on to a horrible if-then every time I add an entity! Any and all help appreciated.

    public bool CreateRecord(object o)
    {
        Audit audit = new Audit()
        {
            ChangeTypeID = (int)Audit.ChangeType.CREATE,
            TimeStamp = GetCurrentDateTime(),
            RecordClass = o.GetType().ToString(),
            NewValue = "",
            ReasonForChange = "Record Creation"
        };

        if (o.GetType() == typeof(Permission))
        {
            Permission x = (Permission)o;
            audit.OriginalValue = x.ToString();
            Permissions.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(User))
        {
            User x = (User)o;
            audit.OriginalValue = x.ToString();
            Users.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(LogIn))
        {
            LogIn x = (LogIn)o;
            audit.OriginalValue = x.ToString();
            LogIns.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(Marker))
        {
            Marker x = (Marker)o;
            audit.OriginalValue = x.ToString();
            Markers.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(Method))
        {
            Method x = (Method)o;
            audit.OriginalValue = x.ToString();
            Methods.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(Sample))
        {
            Sample x = (Sample)o;
            audit.OriginalValue = x.ToString();
            Samples.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(Run))
        {
            Run x = (Run)o;
            audit.OriginalValue = x.ToString();
            Runs.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else if (o.GetType() == typeof(XYDataSet))
        {
            XYDataSet x = (XYDataSet)o;
            audit.OriginalValue = x.ToString();
            XYDataSets.Add(x);
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else
        {
            return false;
        }

        // Save audit record
        audit.UserID = ((App)Application.Current).GetCurrentUserID();
        Audits.Add(audit);
        SaveChanges();

        return true;
    }

Upvotes: 1

Views: 776

Answers (1)

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

I am assuming that all of the entities belongs to same project/assembly, so you can try something like that and notice that this code doesn't tested, modifications might be needed.

    public bool CreateRecord(object o)
    {
        Audit audit = new Audit()
        {
            ChangeTypeID = (int)Audit.ChangeType.CREATE,
            TimeStamp = GetCurrentDateTime(),
            RecordClass = o.GetType().ToString(),
            NewValue = "",
            ReasonForChange = "Record Creation"
        };
        var entityType = Assembly.GetAssembly(typeof(Permission)).GetTypes().Where(x => x == o.GetType())
            .FirstOrDefault(); // Determine the desired entity (assumed all of the entities belongs to same project/assembly)
        if (entityType != null)
        {
            var convertedObject = Convert.ChangeType(o, entityType); // Convert object to entity
            audit.OriginalValue = convertedObject.ToString();
            var entity = yourContext.Set(entityType).Add(convertedObject); // Get DbSet for casted entity
            SaveChanges();
            audit.RecordID = x.ID;
        }
        else
        {
            return false;
        }

        // Save audit record
        audit.UserID = ((App)Application.Current).GetCurrentUserID();
        Audits.Add(audit);
        SaveChanges();

        return true;
    }

Upvotes: 0

Related Questions