2015-12-21 160 views
1

我有2代表在我的数据库:实体框架组合键映射

游戏:

public class Game 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [ForeignKey("WinningSlot"), Column(Order = 0)] 
    public int Id { get; set; } 
    public int numer { get; set; } 
    public string md5 { get; set; } 
    public string secret { get; set; } 
    public GameStatus Status { get; set; } 
    public int SlotsNumber { get; set; } 
    public DateTime CreationTime { get; set; } 
    public DateTime? EndDime { get; set; } 
    public DateTime? ForceEndTime { get; set; } 
    [ForeignKey("WinningSlot"), Column(Order = 1)] 
    public int WinningSlotId { get; set; 
    public GameSlot WinningSlot { get; set; } 
    public double SlotPrice { get; set; } 
    public List<GameSlot> Slots { get; set; } 
} 

GameSlot:

public class GameSlot 
{ 
    [Column(Order = 0), Key] 
    public int GameId { get; set; } 
    [ForeignKey("GameId")] 
    public Game Game { get; set; } 
    [Column(Order = 1), Key] 
    public int Slot { get; set; } 
    public int? PlayerId { get; set; } 
    [ForeignKey("PlayerId")] 
    public WotUser Player { get; set; } 
    public string SecretData { get; set; } 
} 

,你可以看到GameSlot表的PK是复合并由GameID(也是FK到Game)和Slot(它是插槽编号)组成。一切正常,直到我试图将WinningSlot属性添加到我的Game表中。它会在数据库更新的GameSlot表中为它生成另一个Game_Id列。

我所有试图搞糊涂api的尝试都失败了。你能帮助我,请建立一个正常的关系,这个工作? winningslot列是可选的,可以为空。谢谢!

更新: 问题与FluentApi解决:

modelBuilder.Entity<Game>() 
       .HasOptional(g => g.WinningSlot) 
       .WithMany() 
       .HasForeignKey(g => new { g.Id, g.WinningSlotId }); 

但这里是另一个: 当我尝试添加插槽像这样(示例代码),它工作正常:

var game = db.Games.Find(1); 
game.WinningSlotId = 1; 
db.SaveChanges(); 

但如果我想设置插槽,请改为:

var game = db.Games.Find(1); 
var gameslot = db.Slots.Find(game.Id, 1); 
game.WinningSlot = gameslot; 
db.SaveChanges(); 

它会抛出一个异常告诉我,我不能修改游戏的Id属性。这里有什么错误,如果gameslot有它的gameID = game.Id?

回答

1

你可以试试这个:

modelBuilder.Entity<GameSlot>() 
    .HasKey(g => new { g.GameID, g.Slot }) 
    .HasRequired(g => g.Game) 
    .WithMany(g => g.GameSlot); 

编辑:我发现它为什么做索引,你需要让你的导航性能的虚拟。正因为如此,你不需要我上面写的流畅的api,但是我个人发现流式映射比使用数据注解更加清晰,就像你没有通过属性混淆模型一样。

public class Game 
{ 
public Game() 
{ 
    Slots = new HashSet<GameSlot>(); 
} 

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
[ForeignKey("WinningSlot"), Column(Order = 0)] 
public int Id { get; set; } 
public int numer { get; set; } 
public string md5 { get; set; } 
public string secret { get; set; } 
public GameStatus Status { get; set; } 
public int SlotsNumber { get; set; } 
public DateTime CreationTime { get; set; } 
public DateTime? EndDime { get; set; } 
public DateTime? ForceEndTime { get; set; } 
[ForeignKey("WinningSlot"), Column(Order = 1)] 
public int WinningSlotId { get; set;  
public double SlotPrice { get; set; } 

public virtual GameSlot WinningSlot { get; set; } 
public virtual ICollection<GameSlot> Slots { get; set; } 
} 

(更常见于用一个HashSet一起使用界面为您导航集合属性。)

另外如果你想Game可访问从GameSlot,无论是通过懒惰/预先加载,你将有也可以在Game上添加导航属性,但在旁注中添加导航属性。

关于第二个错误,Game.IdGame的主键和GameSlot的外键。如果您尝试指定另一个赢得比赛的游戏,则您也尝试更改GameSlot的Id。