EF models. Navigation properties can only participate in a single relationship

随声附和 提交于 2020-01-24 16:00:11

问题


I have my entities like this, they are closely linked.

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

    public int FirstTeamId { get; set; }
    public Team FirstTeam { get; set; }
    public int SecondTeamId { get; set; }
    public Team SecondTeam { get; set; }

    public Stadium Stadium { get; set; }
    public DateTime Date { get; set; }

    public GameStatus Result { get; set; }

    public Game(DateTime date , GameStatus result )
    {
        Date = date;
        Result = result;
    }
}

public class Player
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public DateTime Birthday { get; set; }
    public PlayerStatus Status { get; set; }
    public PlayerHealthStatus HealthStatus { get; set; }
    public int Salary { get; set; }
    public int TeamId { get; set; }
    public Team Team { get; set; }

    public Player(string name , string surname, DateTime birthday, PlayerStatus status, PlayerHealthStatus healthStatus, int salary)
    {
        Name = name;
        Surname = surname;
        Birthday = birthday;
        Status = status;
        HealthStatus = healthStatus;
        Salary = salary;
    }

}

public class Stadium
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Capacity { get; set; }
    public int PriceForPlace { get; set; }

    public Stadium(string name, int capacity, int priceForPlace)
    {
        Name = name;
        Capacity = capacity;
        PriceForPlace = priceForPlace;
    }
}

public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Player> Players { get; set; }

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

    public Team(string name)
    {
        Name = name;
    }

    public Team(string name, List<Player> players) : this(name)
    {
        Players = players;

    }
}

In my Context class I'm tried to describe my relationships between classes. But something isn't correct.

public class ApplicationContext : DbContext
{
    public DbSet<Player> Players { get; set; }
    public DbSet<Game> Games { get; set; }
    public DbSet<Team> Teams { get; set; }
    public DbSet<Stadium> Stadiums { get; set; }

    public ApplicationContext()
    {
        Database.EnsureCreated();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=best-komp;Database=FootballApplicationDataBase;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Player>()
            .HasOne(p => p.Team)
            .WithMany(t => t.Players)
            .HasForeignKey(p => p.TeamId)
            .HasPrincipalKey(t => t.Id);
        modelBuilder.Entity<Team>()
            .HasMany(p => p.Players)
            .WithOne(p => p.Team)
            .HasForeignKey(p => p.TeamId)
            .HasPrincipalKey(t => t.Id);

        modelBuilder.Entity<Game>()
            .HasOne(g => g.FirstTeam)
            .WithMany(t => t.Games)
            .HasForeignKey(t => t.FirstTeamId)
            .HasPrincipalKey(t => t.Id);
        modelBuilder.Entity<Game>()
            .HasOne(g => g.SecondTeam)
            .WithMany(t => t.Games)
            .HasForeignKey(t => t.SecondTeamId)
            .HasPrincipalKey(t => t.Id);


    }
}

What wrong with this code? Because I have "Navigation properties can only participate in a single relationship." error when I try to do something with my ApplicationContext.


回答1:


You can't reuse Team.Games as the inverse property for both Game.FirstTeam and Team.SecondTeam. Image, if you add game to Team.Games, how would EF know which team it is, first or second?

You need two collections to describe the relationships. And that's also a chance to add some more meaning to the class model. For example (only modified code):

public class Game
{
    ...
    public int HomeTeamId { get; set; }
    public Team HomeTeam { get; set; }
    public int AwayTeamId { get; set; }
    public Team AwayTeam { get; set; }
}

public class Team
{
    ...
    public List<Game> HomeGames { get; set; }
    public List<Game> AwayGames { get; set; }
}

For a team it's meaningful to make a distinction between home and away games, for example to compare results in both types of games.

And the mapping:

modelBuilder.Entity<Game>()
    .HasOne(g => g.HomeTeam)
    .WithMany(t => t.HomeGames)
    .HasForeignKey(t => t.HomeTeamId)
    .HasPrincipalKey(t => t.Id);
modelBuilder.Entity<Game>()
    .HasOne(g => g.AwayTeam)
    .WithMany(t => t.AwayGames)
    .HasForeignKey(t => t.AwayTeamId).OnDelete(DeleteBehavior.NoAction)
    .HasPrincipalKey(t => t.Id);

If using Sql Server, this delete behavior instruction is necessary to prevent disallowed multiple cascade paths.




回答2:


The problem is that your Team model has 2 one-to-many relationships with your Game model but you only have one navigation property on the Team.

You need to have 2 navigation properties on the Team model, one for each relationship. (Game1, Game2...).

You will also need to define these relationships in the Game model - a Team property for each relationship.

Check this answer for extra info.



来源:https://stackoverflow.com/questions/59274852/ef-models-navigation-properties-can-only-participate-in-a-single-relationship

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!