I have a requirement to create an 'audit trail' for CRUD functions to a table but I am puzzled when it comes to the Insert part of the solution:
The issue lies with the Audit
table requiring the ID
of the edited row, however the ID of the table being edited is an IDENTITY
and to make matters worse, the Audit
table is used to audit multiple tables so a foreign key is not possible.
I've created a simplified version of the code and tables:
Tables:
CREATE TABLE Audit
(
ID BIGINT NOT NULL PRIMARY KEY IDENTITY,
TableName VARCHAR(100) NOT NULL,
InsertedID BIGINT NOT NULL, --This is the ID of the row which has been inserted
DateTimeInserted DATETIME NOT NULL
)
CREATE TABLE Customer
(
ID BIGINT NOT NULL PRIMARY KEY IDENTITY,
Name VARCHAR(100),
Surname VARCHAR(100)
)
Code:
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer()
{
Name = "Foo",
Surname = "Bar"
};
using (SampleAuditEntities dbContext = new SampleAuditEntities())
{
InsertAuditTool insertAuditTool = new InsertAuditTool(dbContext);
insertAuditTool.TestInsert(customer);
dbContext.SaveChanges();
}
Console.WriteLine("Customer ID = " + customer.ID);
Console.ReadLine();
}
}
class InsertAuditTool
{
SampleAuditEntities dbContext;
public InsertAuditTool(SampleAuditEntities DbContext)
{
this.dbContext = DbContext;
}
public void TestInsert(Customer InsertedCustomer)
{
Audit audit = new Audit()
{
TableName = "Customer",
DateTimeInserted = DateTime.Now,
InsertedID = InsertedCustomer.ID //Always 0 as it is not assigned until the change is committed.
};
dbContext.Customers.Add(InsertedCustomer);
dbContext.Audits.Add(audit);
}
}
Now normally I would take the approach of committing the Insert of the Model first, call SaveChanges()
and then insert into the audit table but it would be bad practice to potentially allow an insert to be committed and have the audit fail as every insert must be audited (and vice versa).
So my question is, how can I accurately record the new ID of the Inserted row without having 2 separate transactions. Is this approach even possible? If not, what are my options?
Thanks in advance!