Когда роль удаляется у пользователя, мне нужно отслеживать, кто это сделал (например, какой AbpUser) и когда они это сделали.

Очевидным решением является переопределение сущности UserRole так, чтобы она унаследовала от FullAuditedEntity вместо CreationAuditedEntity, но сущность UserRole определена в пакете nuget, поэтому я не могу просто изменить определение.

Есть ли способ добиться такого поведения, которого я не вижу?

Вот что я пытался до сих пор.

Подход 1: я попытался справиться с этим на уровне базы данных, установив триггер удаления в таблице AbpUserRole, который будет вставлять запись в таблицу AbpUserRoleDeleted, но я не могу придумать способ узнать, какой AbpUser сделал удаление с помощью этого подход. Я могу только отследить, когда произошло действие.

Подход 2: я попытался прослушать событие домена EntityDeleted на объектах UserRole, но, похоже, оно не срабатывает. Интересно, что событие EntityUpdated запускается, когда я удаляю роль у пользователя, но даже если предположить, что это событие будет запускаться только при удалении UserRole, данные события по-прежнему не включают того, кто сделал удаление. Если бы это было так, я мог бы вручную сохранить информацию аудита в отдельной таблице, как это сделал бы триггер удаления базы данных, но на этот раз у меня был бы AbpUser, который отвечал за удаление.

Подход 3. Я попытался расширить сущность UserRole, выполнив следующие действия: здесь. Мне удалось реализовать интерфейс IDeletionAudited и сгенерировать миграцию, которая создает связанные столбцы в таблице AbpUserRoles, но удаление роли от пользователя выполняет жесткое удаление вместо мягкого удаления, поэтому я не могу сказать, заполняются ли столбцы . Я предполагаю, что нет.

Подход 4: я попытался включить историю сущностей для сущности UserRole, но, похоже, она отслеживает только то, когда создается сущность UserRole.

-1
yohosuff 15 Апр 2020 в 22:47

1 ответ

Лучший ответ

Кажется, это нормально работает.

//src\aspnet-core\src\Company.App.EntityFrameworkCore\EntityFrameworkCore\AppDbContext.cs
namespace Company.App.EntityFrameworkCore
{
    public class AppDbContext : AbpZeroDbContext<Tenant, Role, User, AppDbContext>, IAbpPersistedGrantDbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
            ChangeTracker.StateChanged += OnEntityStateChanged;
        }

        private void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
        {
            if (e.Entry.Entity is UserRole && e.NewState == EntityState.Deleted)
            {
                //update instead of delete
                e.Entry.State = EntityState.Modified;
                e.Entry.CurrentValues["IsDeleted"] = true;
                e.Entry.CurrentValues["DeletionTime"] = DateTime.Now;
                e.Entry.CurrentValues["DeleterUserId"] = AbpSession.UserId;
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //use query filter on the `IsDeleted` shadow property
            modelBuilder.Entity<UserRole>().HasQueryFilter(p => !EF.Property<bool>(p, "IsDeleted"));
            modelBuilder.Entity<UserRole>().Property<bool>("IsDeleted");
            modelBuilder.Entity<UserRole>().Property<DateTime?>("DeletionTime").IsRequired(false);
            modelBuilder.Entity<UserRole>().Property<long?>("DeleterUserId").IsRequired(false);
        }
    }
}

0
yohosuff 20 Апр 2020 в 20:40