特定实体框架代码首先多对2模型映射

时间:2011-03-17 17:29:21

标签: entity-framework foreign-keys ef-code-first

我在这里有点不知所措。

基本上我有这两个模型:

public class Player
{
    public int PlayerId { get; set; }
    public string Name { get; set; }

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

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

    public virtual Player PlayerBlack { get; set; }
    public virtual Player PlayerWhite { get; set; }
}

现在数据库模式,EF Code First为我创建,是不正确的,因为Game表获得3个外键(Playerblack,PlayerWhite和Player)而不是2。

那么如何将这些模型组合在一起,以便EF了解通过查看黑人或白人玩家可以找到玩家游戏。

基本上每次调用 myPlayer.Games 时,EF都必须查看PlayerBlack和PlayerWhite外键。

甚至可能吗?

2 个答案:

答案 0 :(得分:1)

我相信这是不可能的。您不能在关系的另一侧与单个端点和另一侧的两个端点建立关联。

可能的解决方法:

  • Player类中使用两个集合:

    public virtual ICollection<Game> GamesAsBlackPlayer { get; set; }
    public virtual ICollection<Game> GamesAsWhitePlayer { get; set; }
    

    根据您的上下文,您可以将这些集合合并到一个未映射到数据库的只读集合Games

(编辑:建议的第二个解决方法是废话,现在删除。)

Edit2:另一个workarund可能是通过一个额外的类PlayerInGame来扩展你的类模型:

public class Player
{
    public int PlayerId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<PlayerInGame> PlayerInGames { get; set; }

    // optional helper property
    [NotMapped]
    public IEnumerable<Game> Games
    {
        get
        {
            return PlayerInGames.Select(g => g.Game);
        }
    }
}

public class Game
{
    public int GameId { get; set; }
    public virtual ICollection<PlayerInGame> PlayersInGame { get; set; }

    [NotMapped]
    public Player PlayerBlack
    {
        get
        {
            return PlayersInGame.Single(p => p.WhiteOrBlack == "B").Player;
        }
    }

    [NotMapped]
    public Player PlayerWhite
    {
        get
        {
            return PlayersInGame.Single(p => p.WhiteOrBlack == "W").Player;
        }
    }
}

public class PlayerInGame
{
    public int PlayerInGameId { get; set; }

    public virtual Game Game { get; set; }
    public virtual Player Player { get; set; }
    public string WhiteOrBlack { get; set; }
}

正如您在SinglePlayerBlackPlayerWhite类中的Game方法所看到的那样,您必须确保在您的业务逻辑中创建正确的PlayerInGame个实体,以便您的PlayersInGame集合中始终有两个分别带有黑色或白色标记的元素。

答案 1 :(得分:-1)

我会解决这个问题:

public abstract class Player
{
    public int ID { get; set; }
}

public class WhitePlayer : Player
{
}

public class BlackPlayer : Player
{
}

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

    public virtual WhitePlayer WhitePlayer { get; set; }
    public virtual BlackPlayer BlackPlayer { get; set; }
}

public class GamePlayerContext : DbContext
{
    public DbSet<Game> Games { get; set; }
    public DbSet<Player> Players { get; set; }
}