【发布时间】:2019-09-22 13:09:46
【问题描述】:
- 我有一个带有 sampleItems 的样品。
- 我从 sample 中的 sampleItems 列表中删除了一个 sampleItem。
- 我保存了 DBContext。
我想软删除 sampleItem。
我的代码:
public class Entity: {
public Guid Id { get; set; }
public bool IsDeleted { get; set; }
}
public class Sample : Entity{
public string Text { get; set; }
public List<SampleItem> SampleItems { get; set; } = new List<SampleItem>();
}
public class SampleItem :Entity{
public string Text { get; set; }
public virtual Sample Sample { get; set; }
}
当我从数据库中获取实体时:
var sample = context.Samples.First(s=>s.Id == myId);
sample.SampleItems.RemoveAt(index);
context.SaveChanges();
在 MyDbContext 我有:
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
foreach (var entry in ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Added:
//Do stuff
break;
case EntityState.Modified:
//Do stuff
break;
case EntityState.Deleted:
if (entry.Entity is Entity entity)
{
entry.State = EntityState.Unchanged;
entity.IsDeleted = true;
}
break;
}
}
return base.SaveChangesAsync(cancellationToken);
}
所以我希望我删除的 SampleItem 的 entryState 为 Deleted,但不是,entryState 设置为 Modified。但是当我在操作完成后查看数据库时,sampleItem 被删除了。
在这种情况下如何软删除 sampleItem?
编辑:
我在这里读到:https://github.com/aspnet/EntityFrameworkCore/issues/11240,来自 ajcvickers 的答案是我可以使用“entry.Navigations”。
我注意到 SampleItem 有 NavigationEntries,所有 SampleItems 都在其中,除了我删除的那个。
所以也许我们可以为不在列表中的人想象一个 linq 函数?我目前正在尝试没有成功。有人知道怎么做吗?
var x = ChangeTracker.Entries()
.Where(e => !e.Navigations
.Where(n => !n.Metadata.IsDependentToPrincipal())
.Where(n => n is CollectionEntry)
.Select(n => n as CollectionEntry)
.SelectMany(n => n.CurrentValue.Cast<object>())
.Select(Entry)
.Contains(e)
)
.ToList();
编辑 2
这里:https://github.com/aspnet/EntityFrameworkCore/issues/3815,我找到了禁用级联删除的方法。
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
现在执行 SaveChanges 时出现错误:
"实体 'Sample' 和 'SampleItem' 之间的关联与 键值“{Id: 1c41c336-b75b-4f6b-6057-08d5f3d981ae}”已 已被切断,但该关系要么标记为“必需”,要么 隐式需要,因为外键不可为空。如果 当需要关系时,应删除依赖/子实体 被切断,然后设置关系以使用级联删除。”
(有关级联配置的更多详细信息:https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete)
这是正常的。现在我需要找到禁用删除 SampleItem 并启用 SoftDelete。
你有什么想法吗?
【问题讨论】:
-
我会从一开始就将软删除作为定期更新处理。毕竟,它是更新。对象图中的实体状态错综复杂地相互关联。你不想篡改它们。我从不理解这些将删除重定向到更新的狡猾解决方案。它总是会产生不可预知的副作用。
-
有一天,实体框架团队将默认启用软删除,我希望 ;)。但目前,是的,狡猾的解决方案是一种方法。