两个类之间的实体框架多对多
本文关键字:实体 框架 之间 两个 | 更新日期: 2023-09-27 17:54:59
我正在开发一个简单的MVC应用程序,使用实体框架来跟踪羽毛球联赛的分数。我有以下两类:
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; }
}
和
public class Player
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public List<Game> Games { get; set; }
}
我遇到的问题是,当我有一个玩家的实例时,Games属性会返回一个空列表。当我请求我的玩家列表时,我使用以下内容:-
var players = badmintonDB.Players.Include("Games").ToList();
通过对SO的搜索,我试图覆盖OnModelCreating
。我已经尝试了以下使用和不使用Map()
的操作。这在我的数据库中创建了另一个表,但它不包含任何记录。
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);
}
我看不出哪里出了问题,是需要重新思考POCO的设计,还是在重写OnModelCreating
时语法错误。
如有任何帮助,我们将不胜感激。
我不确定这个设计是否能按照你想要的方式工作。如果你制作了一个新的"Score"实体来将玩家与这样的游戏联系起来呢:
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; }
}
更新:
仔细想想,我不确定这是否可以通过自动导航属性实现。原因是:您在Game
中有两个外键。因此,玩家要加载其游戏列表,EF必须在两个外键上创建一个选择。
旧答案(我现在认为是错误的(:
EF尝试自动检测导航属性。也许这失败了,因为Game
有两个Player
。
自己声明导航:
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);
}
请尝试:
public virtual List<Game> Games { get; set; }
对于代码优先的API,如果要使用延迟加载,则需要将导航属性指定为virtual
。请参阅C#EF Code First虚拟关键字,它有什么作用?
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; }
}
如果启用了延迟加载,并且您没有像使用Map();
那样修改任何关系,则var players = badmintonDB.Players;
应返回所有玩家及其关联的所有游戏。
但是要注意,当使用延迟加载加载数据时,它实际上取决于您的输出。如果你愿意,例如输出JSON字符串中的所有数据,它将加载所有游戏。如果没有,它不会打扰,因为它会认为你不需要任何游戏来展示。