【问题标题】:Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. - How?指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 - 如何?
【发布时间】:2021-04-19 01:17:30
【问题描述】:

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

例如,您有一个 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; }
}

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

public virtual DbSet<Team> Teams { get; set; }
public virtual DbSet<Game> Games { get; set; }

我收到的错误是:

在表“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约束,你是怎么做的呢?

【问题讨论】:

    标签: c# entity-framework entity-framework-core


    【解决方案1】:

    在 EF Core 中,关系的级联行为是通过 OnDelete 关系 Fluent API 配置的(默认情况下,Cascade 与您的 required relationships 类似)。

    棘手的部分是如何访问该 API,因为没有直接的方法(例如,modelBuilder.Relation&lt;TPrincipal, TDependent&gt;()... 之类的东西本来不错,但这样的 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();
    

    现在您可以配置级联行为、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); // <--
    

    有关详细信息,请参阅文档的 RelationshipsEF Core API Reference 部分。

    【讨论】:

    • 完美,就像一个魅力!我还看到了 DeleteBehavior.NoAction。我将研究所有这些选项。再次感谢!
    【解决方案2】:

    在您的 DbContext 类上,您需要添加:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Game>(entity =>
                {
                    entity.Property(e => e.GameId)
                        .HasColumnName("GameID");
    
                    entity.Property(e => e.Team1Id).HasColumnName("Team1ID");
    
                    entity.Property(e => e.Team2Id).HasColumnName("Team2ID");
    
                    entity.HasOne(d => d.Team1)
                        .WithMany(p => p.GameTeam1)
                        .HasForeignKey(d => d.Team1Id)
                        .OnDelete(DeleteBehavior.ClientNoAction)
                        .HasConstraintName("FK_Games_Teams_Team1ID");
    
                    entity.HasOne(d => d.Team2)
                        .WithMany(p => p.GameTeam2)
                        .HasForeignKey(d => d.Team2Id)
                        .OnDelete(DeleteBehavior.ClientNoAction)
                        .HasConstraintName("FK_Games_Teams_Team2ID");
                });
    
                modelBuilder.Entity<Team>(entity =>
                {
                    entity.Property(e => e.TeamId)
                        .HasColumnName("TeamID")
                        .ValueGeneratedNever();
    
                    entity.Property(e => e.TeamName)
                        .IsRequired();
                });
    
                OnModelCreatingPartial(modelBuilder);
            }
    

    整件事并不能完全代表您的需要,但这就是您设置 ondelete 和 onupdate 行为的方式。

    【讨论】:

    • 感谢您的快速回复! p.GameTeam1 和 p.GameTeam2 是什么?这些属性不是 Team 对象的一部分。
    猜你喜欢
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 2021-05-08
    • 2023-01-24
    • 2016-10-15
    • 2012-10-03
    相关资源
    最近更新 更多