I was wondering if anyone could offer some input for an implementation of audit logging for inserts. I need to ensure that it is transactional.
I have an audit DbSet built upon the following POCO:
public class Audit {
public int Id { get; set; }
public User User { get; set; }
public DateTime Created { get; set; }
public string Type { get; set; }
public int EntityId { get; set; }
public string Message { get; set; }
}
I have a DbSet, say Users, that when I do an insert I want to create automatically add an Audit entity in the Audit DbSet. Consider the following code:
//var user = new User();
//user.Created = DateTime.Now;
//user.Username = "testuser";
//user.Password = "testpassword";
//dataContext.Users.Add(user);
var post = new Post();
post.Created = DateTime.Now;
post.Title = "A sample post";
post.Published = true;
post.Body = "Some content goes in here...";
dataContext.Posts.Add(post);
var audit = new Audit();
audit.Created = DateTime.Now;
audit.User = CurrentUser.User; // Currently logged in user
audit.Type = "Post.Add";
audit.EntityId = post.Id;
audit.Message = "New post was created";
dataContext.Audits.Add(audit);
dataContext.SaveChanges();
In this instance, an audit entity will be added but the “EntityId” property will be set to 0 (default value) and not to the identity of the created user post, i.e. the identity value (SCOPE_IDENTITY()/@@IDENTITY).
I’d like to keep both points in a single transaction, rather than split the items into two transactions, i.e. persist the User Post first, then persist the Audit second as there is a chance the Audit may fail.
Override DbContext.SaveChanges() and look at all the ChangeTracker.Entries().Where(e=>e.State != EntityState.Unchanged).
Here is an example from a R&D project of mine: