2015-12-21 118 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。