Почему Entity Framework Soft-Delete через Savechanges? (и альтернативное решение)C#

Место общения программистов C#
Ответить
Anonymous
 Почему Entity Framework Soft-Delete через Savechanges? (и альтернативное решение)

Сообщение Anonymous »

Я хочу реализовать «мягкое удаление» в моем приложении, что означает, что вместо физического удаления записей из базы данных я установил флаг ISDELED в TRUE. Мое ожидание состоит в том, чтобы перехватить процесс удаления в структуре сущности (EF), переопределяя SaveChanges , чтобы любая операция удаления удалялась в мягкое удаление. Когда предприятие отмечено для удаления (EntityState.Deleted), EF рассчитывает выполнить жесткое удаление в базе данных. Переопределение SaveChanges и изменение состояния объекта на «изменение» (для обновления флага IsDeleted работает для основного объекта, но не обрабатывает связанных сущностей с отношениями Cascade Delete. Внутренний механизм удаления каскада EF тесно связан с твердыми удалениями и не запускает мягкие удаления. Это означает, что зависимые объекты не являются мягкими, как ожидалось. Recurusivecascadesoftdelete Метод в моем appdbcontext . Этот метод вручную пересекает все свойства навигации с помощью DeleteBehavior.cascade , загружает связанные объекты и рекурсивно отмечает их как мягкие удаленные путем установки своего Isdeleted флага и обновления их состояния. Это гарантирует, что когда на родительском объекте выполняется мягкое удаление, все зависимые объекты также мягко удаляются, имитируя поведение каскада удаления. < /P>
public int SaveChanges()
{
return _dbContext.SaveChanges();
}

public override int SaveChanges()
{
PrepareEntites();
return base.SaveChanges();
}

private void PrepareEntites()
{
List entities = ChangeTracker.Entries().ToList();

foreach (EntityEntry entity in entities)
{
switch (entity.State)
{
case EntityState.Deleted:
HandleSoftDelete(entity);
break;

case EntityState.Added:
HandleCreate(entity);
break;

case EntityState.Modified:
if (!Convert.ToBoolean(entity.Property(nameof(BaseEntity.IsDeleted)).CurrentValue))
{
HandleUpdate(entity);
}
break;
}
}
}

private void HandleSoftDelete(EntityEntry entity)
{
entity.State = EntityState.Modified;
entity.Property(nameof(BaseEntity.IsDeleted)).CurrentValue = true;
entity.Property(nameof(BaseEntity.DeleteDate)).CurrentValue = DateTime.UtcNow;

SetUserId(entity.Entity, UserProperty.DeleteUserId);

RecursiveCascadeSoftDelete(entity.Entity);
}

private void RecursiveCascadeSoftDelete(BaseEntity mainEntity)
{
IEntityType? entityType = this.Model.FindEntityType(mainEntity.GetType());

if (entityType == null)
return;

foreach (INavigation navigation in entityType.GetNavigations())
{
IForeignKey foreignKey = navigation.ForeignKey;

if (foreignKey.DeleteBehavior != DeleteBehavior.Cascade)
continue;

object? related = navigation.GetGetter().GetClrValue(mainEntity);

if (related == null)
{
EntityEntry entry = Entry(mainEntity);

if (navigation.IsCollection)
entry.Collection(navigation.Name).Load();
else
entry.Reference(navigation.Name).Load();

related = navigation.GetGetter().GetClrValue(mainEntity);
}

if (related is IEnumerable collection)
{
foreach (BaseEntity dependent in collection)
TrySoftDeleteAndRecurse(dependent);
}
else if (related is BaseEntity dependent)
{
TrySoftDeleteAndRecurse(dependent);
}
}
}

private void TrySoftDeleteAndRecurse(BaseEntity dependent)
{
EntityEntry? dependentEntry = ChangeTracker.Entries()
.FirstOrDefault(e => e.Entity == dependent);
dependentEntry ??= Entry(dependent);

if (dependentEntry.State == EntityState.Unchanged || dependentEntry.State == EntityState.Detached)
{
dependentEntry.State = EntityState.Deleted;
}

if (dependentEntry.State != EntityState.Deleted)
return;

dependentEntry.State = EntityState.Modified;
dependentEntry.Property(nameof(BaseEntity.IsDeleted)).CurrentValue = true;
dependentEntry.Property(nameof(BaseEntity.DeleteDate)).CurrentValue = DateTime.UtcNow;

SetUserId(dependentEntry.Entity, UserProperty.DeleteUserId);

RecursiveCascadeSoftDelete(dependentEntry.Entity);
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... ative-solu
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»