EF Core 中的软删除中间表行

Posted

技术标签:

【中文标题】EF Core 中的软删除中间表行【英文标题】:Soft Delete Intermediate Table Row In EF Core 【发布时间】:2021-12-02 01:22:48 【问题描述】:

我需要在多对多关系中使用软删除。

public class EntityA

   public int Id get; set;
   public ICollection<EntityB> BCollection get; set;
   public bool IsDeleted get; set;


public class EntityB

   public int Id get; set;
   public ICollection<EntityA> ACollection get; set;
   public bool IsDeleted get; set;

我可以使用 fluent API 为多对多关系配置中间表。

modelBuilder.Entity<EntityA>()
            .HasMany<EntityB>(s => s.BCollection)
            .WithMany(c => c.ACollection)
            .Map(cs =>
                    
                        cs.MapLeftKey("AId");
                        cs.MapRightKey("BId");
                        cs.ToTable("ABRelationships");
                    );

我的数据库中的所有实体都使用“IsDeleted”标志来使用软删除,并且我正在使用全局查询过滤器来阻止这些实体在正常查询中返回。

        modelBuilder.Entity<EntityA>().HasQueryFilter(x => x.IsDeleted);
        modelBuilder.Entity<EntityB>().HasQueryFilter(x => x.IsDeleted);

如何在中间表周围添加查询过滤器,以便设置 IsDeleted 标志而不是从中间表中删除行,并且在查看我的关系时它不会自动加入?

【问题讨论】:

通过UsingEntity定义中间表并为此实体定义查询过滤器。 【参考方案1】:

Svyatoslav 的评论将我引向了正确的答案,即利用第三个实体并创建一个使用实体。

首先我为 ABRelationship 添加了一个新的实体类

public class ABEntity

    public int Id  get; set; 

    public bool IsDeleted  get; set; 

    [Required]
    [ForeignKey(nameof(EntityA))]
    public int EntityAId  get; set; 

    public EntityA EntityA  get; set; 

    [Required]
    [ForeignKey(nameof(EntityB))]
    public int EntityBId  get; set; 

    public EntityA EntityA  get; set; 


然后我添加了新的集合属性。我将它们设置为使用过滤器从序列化中忽略,因此关系实体未映射到响应。

public class EntityA

   public int Id get; set;
   public ICollection<EntityB> BCollection get; set;
   public bool IsDeleted get; set;

   [JsonIgnore]
   [IgnoreDataMember]
   public virtual ICollection<EntityAB> EntityAB get; set; 


public class EntityB

   public int Id get; set;
   public ICollection<EntityA> ACollection get; set;
   public bool IsDeleted get; set;

   [JsonIgnore]
   [IgnoreDataMember]
   public virtual ICollection<EntityAB> EntityAB get; set; 

然后我使用“UsingEntity”扩展来映射我的关系实体。

            modelBuilder.Entity<EntityA>()
            .HasMany(p => p.BCollection)
            .WithMany(p => p.ACollection)
            .UsingEntity<ABRelationshipEntity>(
                j => j
                    .HasOne(pt => pt.EntityA)
                    .WithMany(t => t.EntityAB)
                    .HasForeignKey(pt => pt.EntityAId),
                j => j
                    .HasOne(pt => pt.EntityB)
                    .WithMany(p => p.EntityAB)
                    .HasForeignKey(pt => pt.EntityBID));

一旦我设置了以上,下面的全局过滤器就可以正确过滤掉软删除的关系。

modelBuilder.Entity<ABRelationshipEntity>().HasQueryFilter(x => x.IsDeleted);

【讨论】:

以上是关于EF Core 中的软删除中间表行的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 6:查找中间表的名称

EF中间表操作

EF4 CTP5 POCO 中的软删除、导航属性

EXcel怎么在表格中间增加一行,

实体框架数据库首先生成多对多中间表,其中没有额外的列

Dot.Net Core 中 Azure blob 容器中的软删除 blob 文件