EF Core之全局删除方案
EF Core之全局删除方案
本文主要对EF Core的级联删除和软删除的全局配置作说明
-
EF Core的外键默认是级联删除的,如果不想这样就只能手动配置,这里提供一种全局配置的方式:
-
DBContext的OnModelCreating就是我们要处理的地方:
protected override void OnModelCreating(ModelBuilder modelBuilder) { var cascadeFKs = modelBuilder.Model.GetEntityTypes() .SelectMany(t => t.GetForeignKeys()) .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade); foreach (var fk in cascadeFKs) { fk.DeleteBehavior = DeleteBehavior.Restrict; } }
-
-
很多情况下我们需要软删除的方案,EF Core启用软删除也是很方便的:
-
这里提供一种全局配置的方案:
public const string _isDeletedProperty = "IsDeleted"; private static readonly MethodInfo _propertyMethod = typeof(EF).GetMethod(nameof(EF.Property), BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(typeof(bool)); private static LambdaExpression GetIsDeletedRestriction(Type type) { var parm = Expression.Parameter(type, "it"); var prop = Expression.Call(_propertyMethod, parm, Expression.Constant(_isDeletedProperty)); var condition = Expression.MakeBinary(ExpressionType.Equal, prop, Expression.Constant(false)); var lambda = Expression.Lambda(condition, parm); return lambda; } protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var entity in modelBuilder.Model.GetEntityTypes()) { //为需要软删除的表增加一个“IsDeleted”的字段,这里可以是bool类型的 //配合EF Core的QueryFilter就可以实现软删除,也可以手动IgnoreQueryFilter来查询数据 if (typeof(ISoftDeletable).IsAssignableFrom(entity.ClrType) == true) { entity.AddProperty(_isDeletedProperty, typeof(bool)); modelBuilder .Entity(entity.ClrType) .HasQueryFilter(GetIsDeletedRestriction(entity.ClrType)); } } } public override int SaveChanges(bool acceptAllChangesOnSuccess) { OnBeforeSaving(); return base.SaveChanges(acceptAllChangesOnSuccess); } //SaveChanges的时候针对删除操作做特殊处理 private void OnBeforeSaving() { foreach (var entry in ChangeTracker.Entries<ISoftDeletable>()) { switch (entry.State) { case EntityState.Added: entry.CurrentValues[_isDeletedProperty] = false; break; case EntityState.Deleted: entry.State = EntityState.Modified; entry.CurrentValues[_isDeletedProperty] = true; break; } } } //软删除的接口,用于标识,需要的表实现该接口即可 public interface ISoftDeletable { }
-
备注:以上方案不适用于有唯一索引的情况,如果要配合唯一索引,可以将IsDeleted字段设置为int或者string类型,UniqueColumn + IsDeleted组成聚合索引。删除的时候IsDeleted字段要变成一个唯一的值。
-