2

我創建了一個ASP.NET MVC4比賽管理系統,它作爲一個包含類TournamentRound對象的集合。我是EF Code First的新手,但我已經瞭解到,EF是supposed to initialize我的集合對象與實例化時觀察到的代理類,只要我聲明它們是虛擬的。爲什麼當我嘗試在下面的代碼中從ASP.NET控制器向它們添加元素時它們爲空?爲什麼不是Entity Framework初始化我的導航集合?

public class Tournament 
{ 
    public int Id { get; set; } 
    [Required] 
    public String Name { get; set; } 
    public virtual ICollection<Contestant> Contestants { get; set; } 
    public virtual ICollection<Round> Rounds { get; set; } 

    public void InitializeDefaults() 
    { 
     var round = new Round("Round 1"); 
     Rounds.Add(round); // Generates NullReferenceException when called from controller 
    } 
} 

public class Round 
{ 
    public long Id { get; set; } 
    public int MaxContestants { get; set; } 
    public String Title { get; set; } 
    public Round() { } 
    public Round(string title) : this() 
    { 
     Title = title; 
    } 
} 

public class MainController { 
    // (...) 
    [HttpPost] 
    public ActionResult CreateTournament(Tournament tournament) 
    { 
     var db = new DataContext(); 
     var dbTournament = db.Tournaments.Create(); 
     dbTournament.Name = tournament.Name; 
     db.Tournaments.Add(dbTournament); 
     dbTournament.InitializeDefaults(); 
     db.SaveChanges(); 
     return RedirectToRoute(new { action = "Main", tournamentId = dbTournament.Id }); 
    } 
} 


public class DataContext : DbContext 
{ 
    public IDbSet<Tournament> Tournaments { get; set; } 
    public IDbSet<Judge> Judges { get; set; } 
    public IDbSet<Contestant> Contestants { get; set; } 
} 

更新

保存實體後重新初始化DataContext的,解決我的問題。但方式不正確。原始問題的立場。

改變的CreateTournament - 方法

[HttpPost] 
public ActionResult CreateTournament(Tournament tournament) 
{ 
    var db = App.ServiceLocator.GetDataBase(); 
    db.Tournaments.Add(tournament); 
    db.SaveChanges(); 
    db.Dispose(); 

    // Reinitializing the datacontext 
    db = App.ServiceLocator.GetDataBase(); 
    var dbTournament = db.GetTournament(tournament.Id); 
    dbTournament.InitializeDefaults(); 
    db.SaveChanges(); 
    return RedirectToRoute(new { action = "Main", tournamentId = dbTournament.Id }); 
} 
+0

乘坐看看:http://stackoverflow.com/questions/4069563/why-is-my-entity-framework-code-first-proxy-collection-null-and-why-cant-i-set – Marthijn

回答

3

像您期望if you were attaching創建dbTournament上下文它只會工作。只有在這種情況下創建集合併爲延遲加載做準備纔有意義。但你是加入dbTournament作爲一個新的實體,在這種情況下,在數據庫中不能有任何依賴Round s可以引用新比賽,因此延遲加載查詢不會返回結果,並且EF首先不會爲延遲加載創建集合。

could apply tricks像安裝了dbTournament第一,之後將其添加到上下文。但是,這隻會產生不必要的數據庫查詢,由懶加載觸發,沒有結果,而且很冒險。在我看來,最簡單和最合理的解決方案是無論是在默認的構造函數的標準集合初始化...

public Tournament() 
{ 
    Rounds = new HashSet<Round>(); 
} 

......或者至少保護您的InitializeDefaults方法:

public void InitializeDefaults() 
{ 
    var round = new Round("Round 1"); 
    if (Rounds == null) 
     Rounds = new HashSet<Round>(); 
    Rounds.Add(round); 
} 
+2

如果我初始化'在構造函數中使用HashSet'時,在稍後的閱讀中會不會阻礙*更改跟蹤代理*,正如Rowan Miller在此SO-answer中引用的那樣? http://stackoverflow.com/a/4069727/507339。我正在''InitializeDefaults'中尋找警衛以保證安全。作爲一個側面說明,我覺得實體框架的這部分文檔記錄不完整(或者我沒有找到它) – Nilzor