简体   繁体   English

实体框架核心 - 两个实体之间的多个一对多关系

[英]Entity Framework Core - Multiple one-to-many relationships between two entities

I have two entities - Team and Game . 我有两个实体 - 团队游戏 A team can have many games (One-To-Many). 一个团队可以有很多游戏(一对多)。

So that would look something like this: 所以这看起来像这样:

 public class Team
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public ICollection<Game> Games { get; set; }
    }

 public class Game
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }

        public int TeamId { get; set; }
        public Team Team { get; set; }
    }

This works nice, but I want to make it a little more refined by splitting the games into two categories - Home and Away games. 这很好用,但我希望通过将游戏分为两类 - Home和Away游戏来使其更加精致。 This will however introduce another relationship between the two entities and I'm not sure how to define it. 然而,这将引入两个实体之间的另一种关系,我不知道如何定义它。

I imagine it will be something like this? 我想它会是这样的?

 public class Team
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public ICollection<Game> HomeGames { get; set; }
        public ICollection<Game> AwayGames { get; set; }
    }

public class Game
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }

        public int HomeTeamId { get; set; }
        public Team HomeTeam { get; set; }

        public int AwayTeamId{ get; set; }
        public Team AwayTeam { get; set; }
    }

Doing this confuses Entity Framework and it can't decide how to settle the relationships. 这样做会混淆实体框架,它无法决定如何解决关系。

Any ideas? 有任何想法吗?

Base on Relationships - EF Core | 基于关系 - EF核心| Microsoft Docs you can use Data Annotations Microsoft Docs您可以使用Data Annotations

Data Annotations 数据注释

There are two data annotations that can be used to configure relationships, [ForeignKey] and [InverseProperty]. 有两个数据注释可用于配置关系,[ForeignKey]和[InverseProperty]。

[ForeignKey] [ForeignKey的]

You can use the Data Annotations to configure which property should be used as the foreign key property for a given relationship. 您可以使用数据注释来配置应将哪个属性用作给定关系的外键属性。 This is typically done when the foreign key property is not discovered by convention. 这通常在按惯例未发现外键属性时完成。

[InverseProperty] [InverseProperty]

You can use the Data Annotations to configure how navigation properties on the dependent and principal entities pair up. 您可以使用数据注释来配置依赖实体和主体实体的导航属性配对方式。 This is typically done when there is more than one pair of navigation properties between two entity types. 当两个实体类型之间存在多对导航属性时,通常会执行此操作。

public class Team
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [InverseProperty("HomeTeam")]
        public ICollection<Game> HomeGames { get; set; }

        [InverseProperty("AwayTeam")]
        public ICollection<Game> AwayGames { get; set; }
    }

public class Game
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }

        public int HomeTeamId { get; set; }
        [ForeignKey("HomeTeamId")]
        public Team HomeTeam { get; set; }

        public int AwayTeamId{ get; set; }
        [ForeignKey("AwayTeamId")]
        public virtual Team AwayTeam { get; set; }
    }

if you use db.Database.Migrate() you will get erro 如果您使用db.Database.Migrate(),您将获得错误

System.Data.SqlClient.SqlException: 'Introducing FOREIGN KEY constraint 'FK_Games_Teams_HomeTeamId' on table 'Games' may cause cycles or multiple cascade paths. System.Data.SqlClient.SqlException:'在'Games'表上引入FOREIGN KEY约束'FK_Games_Teams_HomeTeamId'可能会导致循环或多个级联路径。 Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。 Could not create constraint or index. 无法创建约束或索引。 See previous errors 查看以前的错误

you can make HomeTeamId AwayTeamId int? 你可以让HomeTeamId AwayTeamId int吗? nullable 可空

public class Team
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [InverseProperty("HomeTeam")]
        public ICollection<Game> HomeGames { get; set; }

        [InverseProperty("AwayTeam")]
        public ICollection<Game> AwayGames { get; set; }
    }

public class Game
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }

        public int? HomeTeamId { get; set; }
        [ForeignKey("HomeTeamId")]
        public Team HomeTeam { get; set; }

        public int? AwayTeamId{ get; set; }
        [ForeignKey("AwayTeamId")]
        public virtual Team AwayTeam { get; set; }
    }

or see Cascade Delete - EF Core | 或者参见Cascade Delete - EF Core | Microsoft Docs Microsoft Docs

  • here the full code i tested and working ( db first not code first ) 这里测试和工作的完整代码( db首先不是代码优先

  • for code first use int? 代码首先使用int?

  • for Program.cs 对于Program.cs

     using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; namespace stackoverflow54196199 { public class Team { public int Id { get; set; } public string Name { get; set; } [InverseProperty("HomeTeam")] public ICollection<Game> HomeGames { get; set; } [InverseProperty("AwayTeam")] public ICollection<Game> AwayGames { get; set; } } public class Game { public int Id { get; set; } public DateTime Date { get; set; } public int HomeTeamId { get; set; } [ForeignKey("HomeTeamId")] public Team HomeTeam { get; set; } public int AwayTeamId { get; set; } [ForeignKey("AwayTeamId")] public Team AwayTeam { get; set; } } public class MyContext : DbContext { public DbSet<Game> Games { get; set; } public DbSet<Team> Teams { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Server=.;Integrated Security=true;Initial Catalog=stackoverflow54196199;Persist Security Info=False;"); } } class Program { static void Main(string[] args) { var db = new MyContext(); foreach (var game in db.Games.Include(i => i.AwayTeam).Include(i => i.HomeTeam)) { Console.WriteLine(game.HomeTeam.Name); Console.WriteLine(game.AwayTeam.Name); } Console.ReadLine(); } } } 
  • for stackoverflow54196199.csproj 对于stackoverflow54196199.csproj

     <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" /> </ItemGroup> 

You have to tell Entity Framework which properties in both entities are involved in one association. 您必须告诉实体框架两个实体中的哪些属性涉及一个关联。 In fluent mapping API this is: 在流畅的映射API中,这是:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Team>().HasMany(t => t.HomeGames)
        .WithOne(g => g.HomeTeam)
        .HasForeignKey(g => g.HomeTeamId);
    modelBuilder.Entity<Team>().HasMany(t => t.AwayGames)
        .WithOne(g => g.AwayTeam)
        .HasForeignKey(g => g.AwayTeamId).OnDelete(DeleteBehavior.Restrict);
}

You have to use the fluent API because by default, EF will try to create two foreign keys with cascaded delete. 您必须使用fluent API,因为默认情况下,EF将尝试使用级联删除创建两个外键。 SQL Server won't allow that because of its infamous "multiple cascade paths" restriction. 由于其臭名昭着的“多级联路径”限制,SQL Server将不允许这样做。 One of the keys shouldn't be cascading, which can only be configured by the fluent API. 其中一个键不应该是级联,只能通过流畅的API进行配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在实体框架核心中使用一对多关系更新连接的实体 - Updating connected entities with one-to-many relationships in entity framework core Entity Framework Core:一对多关系 - Entity Framework Core : one-to-many relationships 如何使3个实体之间的一对多关系与Entity Framework Core 2.1一起使用 - 代码优先 - How to make one-to-many relationship between 3 entities work with Entity Framework Core 2.1 - code-first 首先与实体框架代码建立多个一对多关系 - Multiple one-to-many relationships with entity framework code first Entity Framework Core - 两个多对多关系之间的组合 - Entity Framework Core - combination between two many-to-many relationships 实体框架代码优先关系:一对多到多个实体 - Entity Framework Code First Relationships: One to Many to Multiple Entities 实体框架核心中使用两列的一对多关系 - one-to-many relation using two columns in Entity Framework Core EF Core:一对实体之间的一对一和一对多关系 - EF Core: One-to-one and One-to-many Relationships Between a Single Pair of Entities 实体框架:处理两个实体之间的多个关系 - Entity Framework : Handle multiple relationships between two entities EF Core 3 中具有一对多关系的拥有实体 - Owned entities with one-to-many relationships in EF Core 3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM