Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get PrimaryKey value in SavingChangesAsync interceptor #33686

Closed
prrami opened this issue May 7, 2024 · 1 comment
Closed

Get PrimaryKey value in SavingChangesAsync interceptor #33686

prrami opened this issue May 7, 2024 · 1 comment

Comments

@prrami
Copy link

prrami commented May 7, 2024

I have implemented below code in SavingChangesAsync interceptor. I want to implement AuditLogs for each entry/modification in table. How to get primaryKeyValue in case of entry.state == Added. How can I get newly generated Id. Right now I am getting some random value (-9223372036854774807) in case of entry.state==Added.

I have tried to do it with SavedChangesASync also but there I get entry.state as Unchanged always even if entry is Added or Modified.

public override async ValueTask<InterceptionResult<int>> SavingChangesAsync(
DbContextEventData eventData,
InterceptionResult<int> result,
CancellationToken cancellationToken = default)
{

    foreach (var entry in eventData.Context.ChangeTracker.Entries())
    {
        if (entry.State == EntityState.Added ||
            entry.State == EntityState.Modified ||
            entry.State == EntityState.Deleted)
        {
            var primaryKeyValue = GetPrimaryKeyValue(entry);

            var auditLog = new AuditLog
            {
                TableName = entry.Metadata.GetTableName(),
                TablePrimaryKey = primaryKeyValue,
                Action = GetAction(entry.State),
                OldValue = entry.State == EntityState.Added ? null : JsonConvert.SerializeObject(entry.OriginalValues.ToObject()),
                NewValue = JsonConvert.SerializeObject(entry.Entity),
                AuditDate = DateTime.UtcNow,
                AuditUsername = _userEmail
            };

            _auditLogsDbContext.AuditLogs.Add(auditLog);
        }

    }

    // Call the base interceptor method
    return await base.SavingChangesAsync(eventData, result, cancellationToken);
}

private string GetPrimaryKeyValue(EntityEntry entry)
{
    var primaryKey = entry.Metadata.FindPrimaryKey();
    var primaryKeyProperty = primaryKey.Properties.FirstOrDefault();
    return entry.Property(primaryKeyProperty.Name).CurrentValue.ToString();
}
@ajcvickers
Copy link
Member

@prrami Store generated key values are not available until the database has generated these values. This means they will never be available in SavingChangesAsync, since this is called before SQL is sent to the database. They are available in SavedChangesAsync, but it's currently not easy to know the original state of each entity at that point--you will have to maintain your own map, or use events that trigger when the state changes. Improving this is tracked by #32373.

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants