EF Core > 删除实体(软删除)> 实体状态保持不变
EF Core > Delete entity (Soft Delete) > Entity State remains Unchanged
在我的通用基础存储库中,我有以下从数据库中删除实体的简单方法:
public async Task<bool> DeleteAsync(TKey id)
{
var item = await Context.Set<TDb>().FindAsync(id).ConfigureAwait(false);
if (item == null)
return null;
var result = Context.Set<TDb>().Remove(item);
await Context.SaveChangesAsync().ConfigureAwait(false);
return result.State == EntityState.Modified || result.State == EntityState.Deleted;
}
然后在我的数据库上下文中,我通过以下方式在我的保存更改异步中设置影子属性(就像微软建议的那样)(为更清晰起见简化了代码):
public class EfCoreDbContext : DbContext, IUnitOfWork
{
public EfCoreDbContext(
DbContextOptions options
IConfiguration configuration) : base(options)
{
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
ChangeTracker.SetShadowISoftDeletableProperties();
ChangeTracker.SetShadowIUserOwnableProperties(UserResolver);
ChangeTracker.SetShadowIAuditableProperties(UserResolver);
return await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
}
从 SaveChangesAsync
方法可以看出,我已经将影子属性用于其他跟踪项目,例如审计或用户所有权,这些都没有问题。
最后,这里是负责设置软删除的 Change Tracker 代码
public static void SetShadowISoftDeletableProperties(this ChangeTracker changeTracker)
{
changeTracker.DetectChanges();
foreach (var entry in changeTracker.Entries())
{
if (typeof(ISoftDeletable).IsAssignableFrom(entry.Entity.GetType()))
{
if (entry.State == EntityState.Deleted)
{
entry.State = EntityState.Modified;
entry.Property("IsDeleted").CurrentValue = true;
}
else if (entry.State == EntityState.Added)
{
entry.Property("IsDeleted").CurrentValue = false;
}
else
{
entry.Property("IsDeleted").CurrentValue = entry.Property("IsDeleted").OriginalValue;
}
}
}
}
一切正常,IsDeleted
属性 正在数据库中设置成功;然而,当我检查我的 result.State
时,它告诉我实体状态是 Unchanged
(这导致我的 DeleteAsync returns false
),我不太明白。即使在代码中也是可见的,我将状态从 Deleted
更改为 Modified
。
我当然可以忽略这一点,相反,return 保存更改后完全正确(如果出错,之前会失败);但我只是想了解为什么我会得到这种意想不到的状态结果。非常感谢有关此事的任何帮助。
Added
、Modified
和 Deleted
是 pending 状态,表明当 SaveChanges{Async}
叫做。 ChangeTracker.HasChanges()
returns 当存在任何具有此类状态的实体条目时为真。
默认情况下(SaveChanges{Async}
的acceptAllChangesOnSuccess=true
参数),成功后SaveChanges
更新这些状态以反映永久(数据库)这些实体的状态。 Added
和 Modified
变为 Unchanged
,Deleted
变为 Detached
(条目从更改跟踪器中删除)和 ChangeTracker.HasChanges()
returns假的。
您可以通过将 acceptAllChangesOnSuccess=false
传递给 SaveChanges{Async}
来更改它,在这种情况下您会看到挂起状态,但是您不应该忘记调用 ChangeTracker.AcceptAllChanges()
,否则接下来 SaveChanges{Async}
将尝试在数据库中重新应用它们(很可能会失败)。
在我的通用基础存储库中,我有以下从数据库中删除实体的简单方法:
public async Task<bool> DeleteAsync(TKey id)
{
var item = await Context.Set<TDb>().FindAsync(id).ConfigureAwait(false);
if (item == null)
return null;
var result = Context.Set<TDb>().Remove(item);
await Context.SaveChangesAsync().ConfigureAwait(false);
return result.State == EntityState.Modified || result.State == EntityState.Deleted;
}
然后在我的数据库上下文中,我通过以下方式在我的保存更改异步中设置影子属性(就像微软建议的那样)(为更清晰起见简化了代码):
public class EfCoreDbContext : DbContext, IUnitOfWork
{
public EfCoreDbContext(
DbContextOptions options
IConfiguration configuration) : base(options)
{
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
ChangeTracker.SetShadowISoftDeletableProperties();
ChangeTracker.SetShadowIUserOwnableProperties(UserResolver);
ChangeTracker.SetShadowIAuditableProperties(UserResolver);
return await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
}
从 SaveChangesAsync
方法可以看出,我已经将影子属性用于其他跟踪项目,例如审计或用户所有权,这些都没有问题。
最后,这里是负责设置软删除的 Change Tracker 代码
public static void SetShadowISoftDeletableProperties(this ChangeTracker changeTracker)
{
changeTracker.DetectChanges();
foreach (var entry in changeTracker.Entries())
{
if (typeof(ISoftDeletable).IsAssignableFrom(entry.Entity.GetType()))
{
if (entry.State == EntityState.Deleted)
{
entry.State = EntityState.Modified;
entry.Property("IsDeleted").CurrentValue = true;
}
else if (entry.State == EntityState.Added)
{
entry.Property("IsDeleted").CurrentValue = false;
}
else
{
entry.Property("IsDeleted").CurrentValue = entry.Property("IsDeleted").OriginalValue;
}
}
}
}
一切正常,IsDeleted
属性 正在数据库中设置成功;然而,当我检查我的 result.State
时,它告诉我实体状态是 Unchanged
(这导致我的 DeleteAsync returns false
),我不太明白。即使在代码中也是可见的,我将状态从 Deleted
更改为 Modified
。
我当然可以忽略这一点,相反,return 保存更改后完全正确(如果出错,之前会失败);但我只是想了解为什么我会得到这种意想不到的状态结果。非常感谢有关此事的任何帮助。
Added
、Modified
和 Deleted
是 pending 状态,表明当 SaveChanges{Async}
叫做。 ChangeTracker.HasChanges()
returns 当存在任何具有此类状态的实体条目时为真。
默认情况下(SaveChanges{Async}
的acceptAllChangesOnSuccess=true
参数),成功后SaveChanges
更新这些状态以反映永久(数据库)这些实体的状态。 Added
和 Modified
变为 Unchanged
,Deleted
变为 Detached
(条目从更改跟踪器中删除)和 ChangeTracker.HasChanges()
returns假的。
您可以通过将 acceptAllChangesOnSuccess=false
传递给 SaveChanges{Async}
来更改它,在这种情况下您会看到挂起状态,但是您不应该忘记调用 ChangeTracker.AcceptAllChanges()
,否则接下来 SaveChanges{Async}
将尝试在数据库中重新应用它们(很可能会失败)。