我要删除样品项。
我的代码:
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,所有SampleItem都在其中,除了我删除的那个。
那么也许我们可以想象一个不在列表中的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,我找到了一种禁用Cascade删除的方法。
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。
你有个主意吗?
答案 0 :(得分:1)
您可能已经解决了这个问题,但删除sample.SampleItems.RemoveAt(index);
并替换为:
// Do the soft delete
db.IsSoftDelete = true;
db.Entry(activity).State = EntityState.Modified;
db.UserId = userId;
await db.SaveChangesAsync();
然后在您的替代保存更改上:
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;
}
}
}