T-SQL Tips and Tricks: Efficiently Querying Audit Entries created by Entity Framework in MS SQL
Maintaining audit entries in database is required for Healthcare, Financial, Insurance and many other key industries for legal and compliance purpose.
There are many ways to maintain audit entries in database. If you are using Entity Framework to create audit-entries in SQL database, you would need to query these audit-entries. This is useful when you need to display in report or in UI history of the changes made to certain tables by users.
Here is a T-SQL function that can be easily used to query audit entries from the tables created by Entity-Framework.
/*
sharpquest.fun_audit
returns all the audit entries for a given table and given id.
@schemaName - if NULL then dbo is assumed
@tableName - must be passed
@tableIdName - must be passed -
either primary id or parent table id name to get child table audit entries
@tableIdValue - if value is passed, audit entries returned for specific record;
if NULL is passed, audit entries returned for all records for given table
@fieldNames - comma separated list of fields whose old/new values are returned
if NULL is passed, audit for all fields are returned
@UpdatedBy - entries updated by particular user are returned
- if NULL then entries updated by all users are returned
@dateFrom/To - entries updated within specific date range are returned
- if NULL then all entries are returned
example
-- returns all changes in Customer table
select * from common.fun_audit('Customer', 'CustomerId', NULL, NULL, NULL, NULL, NULL);
-- returns changes in Customer table where CustomerId is 15531
select * from common.fun_audit('Customer', 'CustomerId', 15531, NULL, NULL, NULL, NULL);
-- returns changes in Customer table for fields CustomerName,Address where CustomerId is 15531
select * from common.fun_audit('Customer', 'CustomerId', 15531, 'CustomerName,Address', NULL, NULL, NULL);
-- returns changes in Customer table for CustomerName within december,2023
select * from common.fun_audit('Customer', 'CustomerId', NULL, 'CustomerName', NULL, '2023-12-01', '2023-12-31');
*/
create or alter function sharpquest.fun_audit(
@schemaName varchar(100),
@tableName varchar(100),
@tableIdName varchar(100),
@tableIdValue bigint,
@fieldNames varchar(max),
@UpdatedBy bigint,
@dateFrom datetime,
@dateTo datetime
)
returns table
as
return
SELECT ae.EntityTypeName,
aepi.Propertyname AS EntityIdName,
aepi.NewValue AS EntityId,
ae.State,
ae.StateName,
aep.PropertyName,
aep.OldValue AS OldValue,
aep.NewValue AS NewValue,
CreatedDate as UpdatedDate,
ae.CreatedBy
FROM AuditEntries ae WITH (NOlock)
inner join AuditEntryProperties aepi WITH (NOlock)
on ae.AuditEntryid = aepi.AuditEntryid
AND aepi.PropertyName = @tableIdName
inner join AuditEntryProperties aep WITH (NOlock)
on aep.AuditEntryid = ae.AuditEntryid
AND aep.PropertyName <> aepi.PropertyName
AND aep.PropertyName NOT IN ('Created', 'CreatedBy', 'Updated', 'UpdatedBy')
WHERE ae.EntityTypeName = @tableName
AND ae.EntitySetName = ISNULL(@schemaName, 'dbo')
AND (ISNULL(aep.OldValue, '') <> ISNULL(aep.NewValue, ''))
AND (@tableIdValue IS NULL OR aepi.NewValue = @tableIdValue)
AND (@fieldNames IS NULL OR aep.PropertyName IN (SELECT [data] from SplitCommas(@fieldNames)))
AND (@UpdatedBy IS NULL OR ae.CreatedBy = @UpdatedBy)
AND (@dateFrom IS NULL OR [CreatedDate] >= @dateFrom)
AND (@dateTo IS NULL OR convert(date, [CreatedDate]) <= @dateTo)
GO
Join The Discussion