c# - 软删除我的实体的孩子
问题描述
- 我有一个带有 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,我可以使用“entry.Navigations”的 ajcvickers 的答案。
我注意到 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。
你有想法吗?
解决方案
您可能已经解决了这个问题,但删除sample.SampleItems.RemoveAt(index);
并替换为:
// Do the soft delete
db.IsSoftDelete = true;
db.Entry(activity).State = EntityState.Modified;
db.UserId = userId;
await db.SaveChangesAsync();
然后在您的 Override SaveChanges 上:
public bool IsSoftDelete { get; set; }
public override int SaveChanges()
{
...
// Modified State
var modified = this.ChangeTracker.Entries()
.Where(t => t.State == EntityState.Modified)
.Select(t => t.Entity)
.ToArray();
foreach (var entity in modified)
{
if (entity is ITrack)
{
var track = entity as ITrack;
Entry(track).Property(x => x.CreatedDate).IsModified = false;
Entry(track).Property(x => x.CreatedBy).IsModified = false;
track.ModifiedDate = DateTime.UtcNow;
track.ModifiedBy = UserId;
if (IsSoftDelete)
{
track.IsDeleted = true;
track.DeletedDate = DateTime.UtcNow;
track.DeletedBy = UserId;
}
}
}
推荐阅读
- java - 如何在文件夹级别读取 Jenkins 凭据
- android - 嵌套recyclerView动态数据一致性
- java - SQLiteBlobTooBigException:写入数据库时行太大而无法放入 CursorWindow
- google-bigquery - 如何更新(乘以 5 而不是简单地替换)BigQuery 中的嵌套收入字段?
- java - 如何使用 dropwizard 实现 @Auditable
- c# - 为什么我不能使用 Convert.ToInt32 将整数转换为二进制?
- css - How to fix this navigation menu - It wont show up
- webrtc - WebRTC 是否适合广泛播放音频流
- javascript - 使用 JavaScript 保存文件
- flutter - 如何将我声明的变量放入 AssetImage