两个类之间的实体框架多对多

时间:2013-01-22 12:41:13

标签: c# .net entity-framework

我正在研究一个简单的MVC应用程序,使用Entity Framework跟踪羽毛球联赛的得分。我有以下两个类:

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时我是否有错误的语法。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:2)

我不确定该设计是否可以按您希望的方式工作。如果您创建了一个新的“分数”实体来将玩家与这样的游戏联系起来该怎么办:

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; }
}

答案 1 :(得分:1)

<强>更新
在考虑更多关于它的问题时,我不确定是否可以使用自动导航属性。原因是: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);

    }

答案 2 :(得分:0)

请尝试:

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

使用代码优先API,如果要使用延迟加载,则需要将导航属性指定为virtual。 见C# EF Code First virtual keyword, what does it do?

答案 3 :(得分:0)

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;应该返回所有与其关联的游戏的玩家,并且您没有像使用Map();那样修改任何关系。

但是在使用延迟加载加载数据时要注意,这实际上取决于您输出的内容。如果你愿意,例如输出JSON字符串中的所有数据,它将加载所有游戏。如果没有,它就不会打扰,因为它会认为你不需要任何游戏来展示。