ef-core-3.1 - EF Core 级联引用完整性与 DeleteBehavior.Restrict 无法正常工作
问题描述
我首先使用代码创建了一个 sql server 数据库。有两个表具有一对多关系。数据库工作正常并且创建良好。在 sql server 中,如果我尝试删除其中一个分类记录,则会出现错误(参考完整性限制)。这就是我希望它工作的方式。但是在ef core中,如果我删除一个分类dbset.Remove(classification)
,则该分类被删除,客户中的分类设置为null
。我认为这就是它应该如何工作的方式DeleteBehavior.ClientSetNull
。https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete中有一条注释“ EF Core 2.0中的更改”解释了 DeleteBehavior 函数。
I have the next records:
Classification:
Id Name
1 General
2 Others
Customers:
Id Name IdClassification
1 Customer A 1
2 Customer B 2
3 Customer C <null>
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
...
public int? IdClassification { get; set; }
public Classification Classification { get; set; }
}
public class Classification
{
public int Id { get; set; }
public string Name { get; set; }
...
public ICollection<Customer> Customers { get; set; }
}
public class Context : DbContext
{
public virtual DbSet<Classification> Classifications { get; set; }
public virtual DbSet<Customer> Customers { get; set; }
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Classification>(
entity =>
{
entity.HasKey(e => e.Id);
});
modelBuilder.Entity<Customer>(
entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => e.IdClassification);
...
// Claves foráneas
entity.HasOne(c => c.Classification)
.WithMany(x => x.Customers)
.HasForeignKey(x => x.IdClassification)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_Customer_Classification");
});
}
}
有没有办法防止删除 ef core 中的分类记录?(我不想检查是否有任何与分类相关的客户记录,因为我必须将分类与更多表一起使用)。提前致谢。
解决方案
EF Core 3.0 向DeleteBehavior
枚举添加了几个新值 - ClientCascade
, NoAction
, ClientNoAction
. 不幸的是,文档没有更新(API 参考中的枚举值除外),只有ClientNoAction
在 3.0 Breaking Changes - DeleteBehavior.Restrict 中提到了更清晰的语义:
旧行为
在 3.0 之前,
DeleteBehavior.Restrict
在数据库中创建具有语义的外键Restrict
,但也以不明显的方式更改了内部修复。新行为
从 3.0 开始,
DeleteBehavior.Restrict
确保使用Restrict
语义创建外键——即没有级联;抛出约束冲突——同时不影响 EF 内部修复。为什么
进行此更改是为了改善
DeleteBehavior
以直观方式使用的体验,而不会产生意外的副作用。缓解措施
使用 可以恢复以前的行为
DeleteBehavior.ClientNoAction
。
更多信息包含在相关的跟踪问题中 - 12661:更新 DeleteBehavior 使其更加一致和易于理解
老实说,即使在阅读完所有内容后,我也觉得它并不干净,但更令人困惑。Restrict
似乎已过时并替换为NoAction
,无论怎么说,实际上都将加载的相关实体导航属性/FK 设置为null
,从而导致SET NULL
您已经经历过的数据库行为。
在尝试了所有这些之后,唯一符合您期望的选项是前面提到的ClientNoAction:
注意:使用此值是不寻常的。考虑
ClientSetNull
改为使用禁用级联删除来匹配 EF6 的行为。对于被 跟踪的
DbContext
实体,删除相关主体实体时,从属实体中的外键属性值不会更改。这可能会导致实体图不一致,其中外键属性的值与图中的关系不匹配。如果数据库是使用实体框架迁移或
EnsureCreated()
方法从模型创建的,那么如果违反外键约束,数据库中的行为将生成错误。
不管他们在开始时的注意事项。
话虽如此,只需替换Restrict
为即可ClientNoAction
解决问题。不需要数据库迁移,因为此更改仅影响客户端行为。
推荐阅读
- reactjs - ReactJs 导航链接
- icons - 如何在 Mapbox GL JS 中将图标添加到没有 geojsonlayer 的标记
- php - 没有打开wordpress管理面板的wordpress登录用户
- html - 是什么导致网格边框和网格内容之间的间距变窄,我该如何密封它?
- python - 使用 Jupyter 笔记本从 wiki 转储文件创建语料库
- java - java.io.IOException:流不代表 PKCS12 密钥库
- sql - 如何为此类 sql 查询编写循环
- loops - 在单个循环中计算不同的均值
- error-handling - 当序列容器的传播设置为 false 时,如何使 SSIS 包状态失败
- cython - 如何将python函数转换为C函数指针?