Entity Framework Core 2 - 外键约束

Posted

技术标签:

【中文标题】Entity Framework Core 2 - 外键约束【英文标题】:Entity Framework Core 2 - Foreign Key Constraint 【发布时间】:2018-09-28 02:00:16 【问题描述】:

我试图让一个模型有两个对另一个模型的引用。

我已经研究过这个错误,但看到了与以前的 .Net Core 版本相关的建议。

下面是模型

public class Match

    public int ID  get; set; 
    public DateTime MatchDateTime
     get; set; 
    public int LocationID  get; set; 
    public int GroupID  get; set; 
    public int HomeTeamScore  get; set; 
    public int AwayTeamScore  get; set; 
    [Required]
    public int HomeTeamID  get; set; 
    public int AwayTeamID  get; set; 
    public Location Location  get; set; 
    public Group Group  get; set; 

    [Required]
    [ForeignKey("HomeTeamID")]
    public Team HomeTeam  get; set; 
    [ForeignKey("AwayTeamID")]
    public Team AwayTeam  get; set; 

在运行迁移时,我收到此错误:

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

【问题讨论】:

您能否向我们提供OnModelCreating 方法的内容(因为您使用的是 Code First 迁移)?我认为您在modelBuilder.Entity<Match> 关系中存在问题,可能会多次声明,导致多个循环或级联路径。 将你的 fk onelete 设置为限制而不是级联 该错误与任何 .Net 版本无关,它是一个 SQL Server 错误,很清楚地告诉您这是错误的。 Team 的两个 FK 不能都具有级联删除。 @TetsuyaYamamoto:我的 OnModelCreating() 函数中没有代码 @Mardoxx:我不确定我应该使用什么 DataAnnotation 来实现这一点。 【参考方案1】:

当你运行Add-Migration时,它会生成类似下面代码的迁移文件。

migrationBuilder.CreateTable(
name: "Match",
columns: table => new

    ID = table.Column<int>(nullable: false)
        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
    AwayTeamID = table.Column<int>(nullable: false),
    AwayTeamScore = table.Column<int>(nullable: false),
    GroupID = table.Column<int>(nullable: false),
    HomeTeamID = table.Column<int>(nullable: false),
    HomeTeamScore = table.Column<int>(nullable: false),
    LocationID = table.Column<int>(nullable: false),
    MatchDateTime = table.Column<DateTime>(nullable: false)
,
constraints: table =>

    table.PrimaryKey("PK_Match", x => x.ID);
    table.ForeignKey(
        name: "FK_Match_Team_AwayTeamID",
        column: x => x.AwayTeamID,
        principalTable: "Team",
        principalColumn: "Id",
        onDelete: ReferentialAction.Cascade);
    table.ForeignKey(
        name: "FK_Match_Team_HomeTeamID",
        column: x => x.HomeTeamID,
        principalTable: "Team",
        principalColumn: "Id",
        onDelete: ReferentialAction.Cascade);
);

ReferentialAction.NoAction 设置为FK_Match_Team_HomeTeamID

【讨论】:

【参考方案2】:

所以..解决方案真的很简单。

我使外键 ID 可以为空。我不确定是否将两者都设为空是“必需的”

请看下面的代码:

public class Match

public int ID  get; set; 
public DateTime MatchDateTime
 get; set; 
public int LocationID  get; set; 
public int GroupID  get; set; 
public int HomeTeamScore  get; set; 
public int AwayTeamScore  get; set; 
public int? HomeTeamID  get; set; 
public int? AwayTeamID  get; set; 
public Location Location  get; set; 
public Group Group  get; set; 

[Required]
[ForeignKey("HomeTeamID")]
public Team HomeTeam  get; set; 
[ForeignKey("AwayTeamID")]
public Team AwayTeam  get; set; 

【讨论】:

如果你要求可以为空怎么办?

以上是关于Entity Framework Core 2 - 外键约束的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 2.1 中的 ReverseEngineeringGenerator

DetachedLazyLoadingWarning 的 Entity Framework Core 2.1 问题

Entity Framework Core 2 - 外键约束

Entity Framework Core 性能优化

Entity Framework Core 性能优化

Entity Framework Core - EF Core 2.2 - 'Point.Boundary' 属于接口类型('IGeometry')