Entity Framework Many of the many between the two classes
I am working on a simple MVC application using Entity Framework to track badminton league scores. I have the following two classes:
public class Game
{
public int Id { get; set; }
public Player Player1 { get; set; }
public Player Player2 { get; set; }
public int Player1Score { get; set; }
public int Player2Score { get; set; }
}
and
public class Player
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public List<Game> Games { get; set; }
}
The problem is when I have a player instance the Games property returns an empty list. When I request my player list I use the following: -
var players = badmintonDB.Players.Include("Games").ToList();
From a search on SO, I tried to override OnModelCreating
. I have tried the following with Map()
and without it. This creates another table in my database, but it contains no records.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>().HasMany(p => p.Games).WithMany()
.Map(m =>
{
m.ToTable("PlayerGames");
m.MapLeftKey("Player_Id");
m.MapRightKey("Game_Id");
});
base.OnModelCreating(modelBuilder);
}
I don't see where I am going wrong, I need to rethink the design of my POCO or if I have the syntax wrong when overridden OnModelCreating
.
Any help would be appreciated.
source to share
I'm not sure if this project can work the way you want it to. What if you created a new Score object to associate players with these games:
public class Game
{
public int Id { get; set; }
public virtual ICollection<Score> Scores { get; set; }
}
public class Player
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public virtual ICollection<Score> Scores { get; set; }
}
public class Score
{
public int ScoreId { get; set; }
public virtual Player Player { get; set; }
public virtual Game Game { get; set; }
public int Score { get; set; }
}
source to share
Update:
After thinking more about it, I'm not sure if this can be done with automatic navigation properties at all. The reason is this: you have two foreign keys in Game
. Therefore, in order for the player to load their list of games, EF would have to create a selection on two foreign keys.
Old answer (which I believe to be wrong now):
EF is trying to auto-detect navigation properties. Perhaps it is not, since it Game
has two Player
.
Declare the navigation yourself:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder
.Entity<Game>()
.HasRequired(g => g.Player1)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder
.Entity<Game>()
.HasRequired(g => g.Player2)
.WithMany()
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
source to share
Try:
public virtual List<Game> Games { get; set; }
With the first code API, you need to specify the navigation properties as virtual
if you want to use lazy loading. See C # EF Code First virtual keyword, what does it do?
source to share
public class Player
{
public Player()
{
this.Games = new List<Game>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public List<Game> Games { get; set; }
}
var players = badmintonDB.Players;
should return all players with all their associated games if lazy loading is enabled and you haven't changed any of your relationships as you did with Map();
.
But be careful when loading data with lazy loading, which really depends on what you are outputting. If you, for example, output all data in a JSON string, it will load all games. If not, it doesn't bother as it will think that you won't need any games.
source to share