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

发布于 2024-10-22 12:32:43 字数 633 浏览 2 评论 0原文

我在这里有点失落。

基本上我有这两个模型:

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 为我创建的数据库架构不正确,因为游戏表有 3 个外键(Playerblack、PlayerWhite 和 Player)而不是 2 个。

那么我怎样才能将这些模型绑定在一起呢? EF 了解玩家游戏是通过查看黑人或白人玩家来找到的。

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

有可能吗?

I'm a bit of a loss here.

Basically I have these two Models:

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

Now the Database Schema, EF Code First creates for me, is not correct because the Game table gets 3 Foreign Keys (Playerblack, PlayerWhite and Player) instead of 2.

So how can I tie these Models together so that EF understands that the Players Games are found by either looking at the Black or White Player.

Basically each time I call myPlayer.Games EF has to look into PlayerBlack AND PlayerWhite Foreign Keys.

Is it even possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我太投入 2024-10-29 12:32:43

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

可能的解决方法:

  • Player 类中使用两个集合:

    公共虚拟ICollection; GamesAsBlackPlayer { 获取;放; }
    公共虚拟ICollection<游戏>; GamesAsWhitePlayer { 获取;放; }
    

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

(编辑:建议的第二个解决方法很糟糕,现在已删除。)

Edit2:另一个解决方法可能是通过附加类 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; }
}

正如您可以通过 SingleGame 类中的 PlayerBlackPlayerWhite 属性中的方法,您必须确保在业务逻辑中创建正确的 PlayerInGame 实体,以便您的 PlayersInGame 集合始终包含两个分别带有 Black 或 White 标志的元素。

I believe it's not possible. You cannot have an association with a single endpoint on one side and two endpoints on the other side of the relation.

Possible workarounds:

  • Use two collections in the Player class:

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

    Depending on your context you could perhaps merge these collections together to a readonly collection Games which is not mapped to the database.

(Edit: Proposed second workaround was crap, deleted now.)

Edit2: Another workarund could be to extend you class model by an additional class 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; }
}

As you can see by the Single method in the PlayerBlack and PlayerWhite properties in the Game class you have to make sure in your business logic to create the proper PlayerInGame entities so that your PlayersInGame collection always has two elements with Black or White flag respectively.

游魂 2024-10-29 12:32:43

我会这样解决这个问题:

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

I would tackle the problem like this:

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; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文