简体   繁体   中英

Update before any delete in entity framework

For auditing purposes I need to update a column "UpdatedBy" on certain tables before rows are deleted, which will trigger some third party auditing.

My current solution is to create a custom SaveChanges method on my Context class, but any changes I make to my deleted entities are ignored, and the SQL generated is just a DELETE command.

Is it possible to trigger both an UPDATE and DELETE for the entities in the SaveChanges method?

CS Code

public partial class MyContext : DbContext
{
    public int SaveChanges(int userId)
    {
        foreach (var entry in ChangeTracker.Entries<Auditable>())
        {
            if (entry.State == EntityState.Deleted)
            {
                entry.Entity.UpdatedBy = userId;
            }
        }

        return base.SaveChanges();
    }
}

Example SQL Generated

DELETE FROM EntityTable
WHERE Id = @00

Desired SQL

UPDATE EntityTable
SET UpdateBy = @00
WHERE Id = @01

DELETE FROM EntityTable
WHERE Id = @01

Update

To clarify, I am using a third party auditing framework that created new rows in a separate database. The purpose of performing the UPDATE before the DELETE is to allow the separate database to store the user id that performed the delete. So, although the row is removed from the original database, the audit row needs to be created, which is triggered by the UPDATE.

Entity Framework cannot be forced to perform the UPDATE as well as the DELETE, but I can generate SQL to manually call the update instead. And run the changes in a transaction.

    int SaveChangesWithDelete(int userId)
    {
        using (var tx= Database.BeginTransaction()) //Begin a new transaction
        {
            var entitiyGroups = ChangeTracker.Entries()
                .Where(e => e.State == EntityState.Deleted && e.Entity is Auditable)
                .Select(e => e.Entity)
                .GroupBy(d => d.GetType();

            foreach (var entityGroup in entitiyGroups) //Loop through deleted entities and run a manual UPDATE 
            {
                string query = string.Format(@"
                    UPDATE {0} SET UpdatedBy = {1}
                    WHERE Id IN ({2})
                ", entityGroup.Key.Name, userId, string.Join(",", entityGroup.Select(e => PrimaryKeyValue(e))));

                Database.ExecuteSqlCommand(query); //Execute the query - this triggers the audit framework
            }

            int result = SaveChanges();     //save the context changes as normal
            tx.Commit();                    //commit the transaction
            return result;                  //return the result
        } 
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM