【问题标题】:Entity Framework Many To Many between two classes两个类之间的实体框架多对多
【发布时间】:2013-01-22 12:41:13
【问题描述】:

我正在使用实体框架开发一个简单的 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 时是否有语法错误。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# .net entity-framework


    【解决方案1】:

    我不确定该设计是否可以按您希望的方式工作。如果你创建一个新的“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; }
    }
    

    【讨论】:

    • 感谢 Britton 我在重新设计模型时使用了您的想法。我现在有一个包含结果列表的游戏实体。每个参加比赛的玩家一个。这使我可以通过 EF 访问所有链接信息。
    【解决方案2】:

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

    【讨论】:

    • 您好斯蒂芬,感谢您的建议。我对 OnModelCreating 进行了您建议的更改,但是现在抛出了一个异常:System.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'Game_Player1_Source' in relationship 'Game_Player1'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'. 还有什么我需要设置的吗?
    • 您好 Stephan,看来我可能需要调整我的设计以使其正常工作。我尝试将 Game 类中的 Player1 和 Player2 属性更改为表示 Players 表中的 Id 的整数。但是我仍然需要一种访问播放器对象的方法。有什么想法吗?
    • 你好 53AN。我认为您需要将播放器一和二视为 List 或更好的 List 新类“分数”。 @Britton 走在正确的轨道上。
    【解决方案3】:

    请尝试:

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

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

    【讨论】:

    • 您好,Ken,我将 Games 属性更改为虚拟,但列表仍然为空。即使我知道我的数据库中有给定用户的游戏。我认为 virtual 关键字允许延迟加载,在我目前的情况下,我总是需要给定玩家的游戏列表。我认为我需要以某种方式指示 EF 将值插入到新的 PlayerGames 表中,这种关系足以让它能够填充游戏列表。
    【解决方案4】:
    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 字符串输出所有数据,它将加载所有游戏。如果没有,它不会打扰,因为它会认为你不需要任何游戏来展示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      相关资源
      最近更新 更多