Rob*_* J. 3 c# delete-row ef-core-3.1
在我的通用基础存储库中,我有以下简单的方法用于从数据库中删除实体:
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;
}
Run Code Online (Sandbox Code Playgroud)
然后在我的数据库上下文中,我按照以下方式在异步保存更改中设置影子属性(就像微软建议的那样)(为了更清晰而简化了代码):
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);
}
}
Run Code Online (Sandbox Code Playgroud)
从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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常,IsDeleted属性已在数据库中成功设置;但是,当我检查 my 时result.State,它告诉我实体状态是Unchanged(这导致我的 DeleteAsync 返回false),我不太明白。即使在代码中也是可见的,我将状态从 更改Deleted为Modified。
我当然可以忽略这一点,而是在保存更改后返回纯真(如果出现错误,它之前会失败);但我只是想理解为什么我会得到这种意想不到的状态结果。任何有关此事的帮助将不胜感激。
Added、Modified和Deleted是挂起SaveChanges{Async}状态,指示 EF Core 在调用时将对该实体执行什么操作。ChangeTracker.HasChanges()当存在任何具有这种状态的实体条目时返回 true。
默认情况下(acceptAllChangesOnSuccess=true的参数SaveChanges{Async}),成功后SaveChanges这些状态将更新以反映这些实体的永久(数据库)状态。Added并Modified成为Unchanged,Deleted成为Detached(并且条目从更改跟踪器中删除)并ChangeTracker.HasChanges()返回 false。
您可以通过传递acceptAllChangesOnSuccess=falseto 来更改它SaveChanges{Async},在这种情况下您将看到挂起的状态,但是您不应该忘记调用ChangeTracker.AcceptAllChanges(),否则下一个SaveChanges{Async}将尝试在数据库中重新应用它们(很可能会失败)。