从本地集合中删除项目而不删除

Posted

技术标签:

【中文标题】从本地集合中删除项目而不删除【英文标题】:Remove an item from a local collection without deleting 【发布时间】:2021-02-15 15:42:30 【问题描述】:

我有以下设置:

public class Foo

    public int FooId  get; private set; 


public class Bar

    public int FooId  get; private set; 
    public Foo Foo  get; private set; 

    private readonly List<Baz> _bazes= new List<Baz>();
    public IReadOnlyCollection<Baz> Bazes => _bazes.AsReadOnly();

    public Baz AddBaz(Baz baz)
    
        _bazes.Add(baz);
    

    public void RemoveBaz(Baz baz)
    
        baz.Delete();
        _bazes.Remove(baz);
    


public class Baz

    public int BazId  get; private set; 

    public int FooId  get; private set; 
    public Foo Foo  get; private set; 

    public int QuxId  get; private set; 
    public Qux Qux  get; private set; 

    public DateTime? DateDeleted  get; private set; 

    public void Delete()
    
        DateDelete = DateTime.UtcNow;
    


public class Qux

    public int QuxId  get; private set; 

这都是通过 EF Core 管理的:

在 Foo ->

builder.HasKey(k => k.FooId);
builder.Property(p => p.FooId).ValueGeneratedOnAdd();

在酒吧 ->

builder.HasKey(k => k.FooId);
builder.Property(p => p.FooId).ValueGenerateNever();

builder.HasMany(hm => hm.Baz).WithOne().HasForeignKey(fk => fk.FooId);

在巴兹 ->

builder.HasQueryFilter(qf => !qf.DateDeleted.HasValue);

builder.HasKey(k => k.BazId);
builder.Property(p => p.BazId).ValueGeneratedOnAdd();

builder.HasOne(ho => ho.FooId).WithMany().HasForeignKey(fk => fk.FooId);
builder.HasOne(ho => ho.QuxId).WithMany().HasForeignKey(fk => fk.QuxId);

在 Qux 上 ->

builder.HasKey(k => k.QuxId);
builder.Property(p => p.QuxId).ValueGenerateOnAdd();

除了尝试删除 Baz 时,所有这些都完全按照需要进行。因为我只想软删除,所以我调用 Baz.Delete(),但我还需要从 Bar._bazes 中删除它,否则我的单元测试仍然显示它在对象上。这个问题是它试图从数据库中硬删除 Baz,这是我不想要的,我收到了一个错误:

“实体类型 'Foo' 和 'Baz' 之间的关联已被切断,但该关系要么被标记为‘必需’,要么是隐式必需的,因为外键不可为空。如果依赖/子实体应在所需关系被切断时删除,然后将关系设置为使用级联删除。考虑使用 'DbContextOptionsBuilder.EnableSensitiveDataLogging' 来查看键值。"

有没有办法解决这个问题?在理想情况下,Baz 应仅软删除,但仍应从 Bar 上的 baze 集合中删除

【问题讨论】:

就我个人而言,我不会打扰...但是您可以覆盖 SaveChanges / SaveChangesAsync 并运行保存前和保存后的方法,将删除转换为更新,然后分别从跟踪更改中删除。 嗨@JGillardCCG,关于这个案例有什么更新吗? 由于时间限制,我们选择硬删除 Baz 在我看来,你硬删除的唯一原因是在本地集合中删除Baz后执行Savechange方法,这会导致数据库更新。 【参考方案1】:

我认为您将执行硬删除,因为您在调用RemoveBaz 方法之后调用了Context.Savechange 方法。

RemoveBaz之后,你的List&lt;Baz&gt;删除了Baz,然后你执行SavaChange,这将执行硬删除。

您应该在Savechange 之后编写您的RemoveBaz 方法。

像这样更改您的RemoveBaz

public void RemoveBaz(Baz baz)
    
        _bazes.Remove(baz);
    

那么删除顺序应该是baz.Delete()=>SaveChange=>bar.RemoveBaz(baz)

这是你的问题测试:

这是我的解决方案测试:

【讨论】:

你读过这个问题吗?他已经做到了这一点。 如果我的回答对你有用,可以标记为答案,对以后遇到同样问题的人有帮助。

以上是关于从本地集合中删除项目而不删除的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ListView 中删除项目而不从数据库中删除它?

我可以从 ComboBox 中删除项目而不更改其他项目的索引吗?

从集合视图中删除项目后的标签问题

如何从集合视图中删除项目?

从集合中删除项目时出错[重复]

从 SVN 存储库中删除文件而不删除本地副本