DeleteBehavior.Restrict 的 EF Core 级联引用完整性无法正常工作
EF Core Cascading Referential Integrity with DeleteBehavior.Restrict does not work well
我有一个 sql 服务器数据库先用代码创建。有两个表具有一对多关系。该数据库运行良好并且创建良好。
在 sql 服务器中,如果我尝试删除其中一个分类记录,则会出现错误(引用完整性限制)。这就是我希望它工作的方式。但是在ef core中,如果我删除了一个分类dbset.Remove(classification)
,分类被删除,customer中的分类设置为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中的分类记录吗? (我不想检查是否有任何客户记录链接到分类,因为我必须将分类与更多表一起使用)。
提前致谢。
嗯,分类实体需要正确初始化,假设删除限制规则。
modelBuilder.Entity<Classification>()
.HasKey(e => e.Id)
.HasMany(e => e.Customers)
.WithOne(e => e.Classification)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(true);
希望对您有所帮助。
EF Core 3.0 向 DeleteBehavior
枚举添加了几个新值 - ClientCascade
、NoAction
、ClientNoAction
。不幸的是,文档没有更新(API 参考中的枚举值除外),并且 3.0 重大更改中仅提到了 ClientNoAction
- DeleteBehavior.Restrict has cleaner semantics:
Old behavior
Before 3.0, DeleteBehavior.Restrict
created foreign keys in the database with Restrict
semantics, but also changed internal fixup in a non-obvious way.
New behavior
Starting with 3.0, DeleteBehavior.Restrict
ensures that foreign keys are created with Restrict
semantics--that is, no cascades; throw on constraint violation--without also impacting EF internal fixup.
Why
This change was made to improve the experience for using DeleteBehavior
in an intuitive manner, without unexpected side-effects.
Mitigations
The previous behavior can be restored by using DeleteBehavior.ClientNoAction
.
相关跟踪问题中包含更多信息 - 12661: Update DeleteBehavior to be more consistent and understandable
老实说,即使阅读了所有这些内容,我也不觉得它更清晰,但更令人困惑。 Restrict
似乎已过时并被 NoAction
取代,无论实际说了什么 确实 将加载的相关实体导航 property/FK 设置为 null
,从而导致 SET NULL
数据库行为,正如您已经经历过的那样。
在尝试了所有这些之后,唯一符合您期望的选项是上述 ClientNoAction:
Note: it is unusual to use this value. Consider using ClientSetNull
instead to match the behavior of EF6 with cascading deletes disabled.
For entities being tracked by the DbContext
, the values of foreign key properties in dependent entities are not changed when the related principal entity is deleted. This can result in an inconsistent graph of entities where the values of foreign key properties do not match the relationships in the graph.
If the database has been created from the model using Entity Framework Migrations or the EnsureCreated()
method, then the behavior in the database is to generate an error if a foreign key constraint is violated.
不管他们开头的注释是什么。
综上所述,只需将 Restrict
替换为 ClientNoAction
即可解决问题。不需要迁移数据库,因为此更改仅影响客户端行为。
我有一个 sql 服务器数据库先用代码创建。有两个表具有一对多关系。该数据库运行良好并且创建良好。
在 sql 服务器中,如果我尝试删除其中一个分类记录,则会出现错误(引用完整性限制)。这就是我希望它工作的方式。但是在ef core中,如果我删除了一个分类dbset.Remove(classification)
,分类被删除,customer中的分类设置为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中的分类记录吗? (我不想检查是否有任何客户记录链接到分类,因为我必须将分类与更多表一起使用)。 提前致谢。
嗯,分类实体需要正确初始化,假设删除限制规则。
modelBuilder.Entity<Classification>()
.HasKey(e => e.Id)
.HasMany(e => e.Customers)
.WithOne(e => e.Classification)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(true);
希望对您有所帮助。
EF Core 3.0 向 DeleteBehavior
枚举添加了几个新值 - ClientCascade
、NoAction
、ClientNoAction
。不幸的是,文档没有更新(API 参考中的枚举值除外),并且 3.0 重大更改中仅提到了 ClientNoAction
- DeleteBehavior.Restrict has cleaner semantics:
Old behavior
Before 3.0,
DeleteBehavior.Restrict
created foreign keys in the database withRestrict
semantics, but also changed internal fixup in a non-obvious way.New behavior
Starting with 3.0,
DeleteBehavior.Restrict
ensures that foreign keys are created withRestrict
semantics--that is, no cascades; throw on constraint violation--without also impacting EF internal fixup.Why
This change was made to improve the experience for using
DeleteBehavior
in an intuitive manner, without unexpected side-effects.Mitigations
The previous behavior can be restored by using
DeleteBehavior.ClientNoAction
.
相关跟踪问题中包含更多信息 - 12661: Update DeleteBehavior to be more consistent and understandable
老实说,即使阅读了所有这些内容,我也不觉得它更清晰,但更令人困惑。 Restrict
似乎已过时并被 NoAction
取代,无论实际说了什么 确实 将加载的相关实体导航 property/FK 设置为 null
,从而导致 SET NULL
数据库行为,正如您已经经历过的那样。
在尝试了所有这些之后,唯一符合您期望的选项是上述 ClientNoAction:
Note: it is unusual to use this value. Consider using
ClientSetNull
instead to match the behavior of EF6 with cascading deletes disabled.For entities being tracked by the
DbContext
, the values of foreign key properties in dependent entities are not changed when the related principal entity is deleted. This can result in an inconsistent graph of entities where the values of foreign key properties do not match the relationships in the graph.If the database has been created from the model using Entity Framework Migrations or the
EnsureCreated()
method, then the behavior in the database is to generate an error if a foreign key constraint is violated.
不管他们开头的注释是什么。
综上所述,只需将 Restrict
替换为 ClientNoAction
即可解决问题。不需要迁移数据库,因为此更改仅影响客户端行为。