同一类型的多个导航属性的关系配置?

Posted

技术标签:

【中文标题】同一类型的多个导航属性的关系配置?【英文标题】:Relashionship configuration of multiple navigation properties of same type? 【发布时间】:2021-06-08 08:59:21 【问题描述】:

1) 我正在尝试在两个类之间建立关系。所以,我有以下课程

 public class Team

    [Key]        
    public int Id  get; set; 

    public string Team  get; set; 

    public List<MatchGame> MatchGames  get; set; 

public class MatchGame

    [Key]
    public int Id  get; set; 

    public int HomeTeamId  get; set; 
    public Team HomeTeam  get; set; 
   
    public int AwayTeamId  get; set; 
    public Team AwayTeam  get; set; 


我尝试执行 relashioship 的配置是

   protected override void OnModelCreating(ModelBuilder modelBuilder)
    

        modelBuilder.Entity<MatchGame>()
            .HasOne(h => h.HomeTeam)
            .WithMany(m => m.MatchGames)
            .HasForeignKey(k => k.HomeTeamId)
            .OnDelete(DeleteBehavior.Cascade);

        modelBuilder.Entity<MatchGame>()
            .HasOne(h => h.AwayTeam)
            .WithMany(m => m.MatchGames)
            .HasForeignKey(k => k.AwayTeamId)
            .OnDelete(DeleteBehavior.NoAction);
    

产生的错误是:

无法在“Team.MatchGames”和 'MatchGame.AwayTeam' 因为两者之间已经存在关系 “Team.MatchGames”和“MatchGame.HomeTeam”。导航属性可以 只参与单一的关系。如果你想覆盖一个 导航上的现有关系调用“忽略” 'MatchGame.AwayTeam' 首先在 'OnModelCreating' 中。

我也看过下面的帖子,但找不到关系无法建立的原因。

EF code first: one-to-many twice to same collection type

https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/relationships

EFCore - How to have multiple navigation properties to the same type?

2) 另外,为了不创建新帖子:我希望团队类中的 public string Team get; set; 是唯一的。我尝试了一些我见过但没有用的 DataAnnotation。为此我必须使用什么。

【问题讨论】:

@philipxy 这个帖子似乎很清楚,解释性很好,显示了适当的研究 我的错误是我还问了另一个问题,但我认为这没什么大不了的,因为它试图找到一个数据注释。我的意图不是仅仅为数据注释创建一个新帖子 【参考方案1】:

问题是您尝试使用一个导航属性MatchGames 来定义关系。尝试创建两个单独的导航属性,如下所示。

public class Team

    public int Id  get; set; 
    public string TeamName  get; set; 
    public List<Match> HomeMatches  get; set; 
    public List<Match> AwayMatches  get; set; 


public class MatchGame

    public int Id  get; set; 
    public int HomeTeamId  get; set; 
    public Team HomeTeam  get; set; 
    public int AwayTeamId  get; set; 
    public Team AwayTeam  get; set; 


protected override void OnModelCreating(ModelBuilder modelBuilder)

    modelBuilder.Entity<MatchGame>(entity =>
    
        entity.HasOne(m => m.HomeTeam)
           .WithMany(t => t.HomeMatches)
           .HasForeignKey(m => m.HomeTeamId)
           .IsRequired()
           .OnDelete(DeleteBehavior.Cascade);

        entity.HasOne(m => m.AwayTeam)
           .WithMany(t => t.AwayMatches)
           .HasForeignKey(m => m.AwayTeamId)
           .IsRequired()
           .OnDelete(DeleteBehavior.Cascade);
    );

广告2.您需要在TeamName上创建唯一索引:

modelBuilder.Entity<Team>(e => e.HasIndex(t => t.TeamName).IsUnique());

你也可以考虑在你的模型中添加MaxLength属性等等。

【讨论】:

感谢您的回答。我将第二个.OnDelete(DeleteBehavior.Cascade); 修改为 ActionNone,因为它无法创建表。它不接受两个.OnDelete(DeleteBehavior.Cascade); 产生的错误号:1785,状态:0,类:16 在表“MatchGames”上引入 FOREIGN KEY 约束“FK_MatchGames_Teams_HomeTeamId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束或索引。查看以前的错误。 顺便说一句,我不明白为什么我尝试与一个导航属性建立关系的方式不起作用。我在 .Net Framework 4.7 中以相同的方式实现了它,并在 .net core 5 上进行了尝试。加上我通过创建此线程提交的线程,呈现了我尝试实现的方式。 为什么在其他类似情况下使用一个导航属性? 我理解它的方式是因为拥有两个外键的一个导航属性,实体框架无法了解要从外键加载哪些数据。

以上是关于同一类型的多个导航属性的关系配置?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 实体关系的配置

EF Core 5.0 中的多对多关系是不是可以配置为仅保留一个导航属性(在一侧)?

Entity Framework Core 实体关系的配置

EF Code First导航属性一对一关系中注意点及配置方法

“NameOfProperty”不能用作实体类型“NameOfType”的属性,因为它被配置为导航

Include路径表达式必须引用在类型EF上定义的导航属性。使用关系表[duplicate]