指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。- 如何?

Car*_* Jr 5 c# entity-framework entity-framework-core

这个问题很容易复制,但我不知道解决它的正确方法。

例如,您有一个Team类和一个Game类。每场比赛有两支球队。使用标准 OOTB EF 命名约定时,在运行dotnet ef database update时会遇到以下错误(dotnet ef migrations add将正常运行)。

课程:

public class Team
{
    [Required]
    public int TeamID { get; set; }
    public string TeamName { get; set; }
}

public class Game
{
    [Required]
    public int GameID { get; set; }
    public int Team1ID { get; set; }
    public Team Team1 { get; set; }
    public int Team2ID { get; set; }
    public Team Team2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

确保将这两个类添加到您的 DbContext 中:

public virtual DbSet<Team> Teams { get; set; }
public virtual DbSet<Game> Games { get; set; }
Run Code Online (Sandbox Code Playgroud)

我收到的错误是:

在表“Games”上引入 FOREIGN KEY 约束“FK_Games_Teams_Team2ID”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

我以前通过使Team1IDTeam2ID 都可以为空来解决这个问题。但是,这显然不是合适的解决方案。如果没有恰好两个团队,游戏就无法存在(在这种情况下......假设它是一场足球比赛)。此外,如果一个团队正在参加(或参加)至少一场比赛,则不应被删除。

解决此问题的适当方法是什么?如果它指定 ON DELETE NOT ACTION 或 ON UPDATE NO ACTION,或者修改其他 FOREIGN KEY 约束,你怎么做?

Iva*_*oev 8

在 EF Core 中,关系的级联行为是通过OnDelete关系 Fluent API配置的(默认情况下,它Cascade用于像您这样的必需关系)。

棘手的部分是如何访问该 API,因为没有直接的方法(例如,像modelBuilder.Relation<TPrincipal, TDependent>()...这样的东西本来很好,但这样的 API 不存在),所以至少你需要从实体类型构建器开始,然后通过适当的Has{One|Many}/With{One|Many}对。正确的意思是在存在时传递相应的导航属性。不这样做会导致意外的额外关系/FK,因为 EF Core 会将未映射的导航属性映射到默认的常规关系/FK。

在你的情况下,它会是这样的:

modelBuilder.Entity<Game>()
    .HasOne(e => e.Team1)
    .WithMany();

modelBuilder.Entity<Game>()
    .HasOne(e => e.Team2)
    .WithMany();
Run Code Online (Sandbox Code Playgroud)

现在您可以配置级联行为、FK 属性/约束名称等。

在这种特殊情况下,只需插入.OnDelete(DeleteBehavior.Restrict)两个关系即可完成:

modelBuilder.Entity<Game>()
    .HasOne(e => e.Team1)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict); // <--

modelBuilder.Entity<Game>()
    .HasOne(e => e.Team2)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict); // <--
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅文档的关系EF Core API 参考部分。