我正在创建一个 ASP.NET MVC4 锦标赛管理系统,它作为一个包含类 Tournament 与集合 Round 对象。我是 EF Code First 的新手,但我知道 EF 是 应该初始化 我的集合对象在实例化时具有观察到的代理类,只要我将它们声明为虚拟的。当我尝试从下面的代码中的 ASP.NET 控制器向它们添加元素时,为什么它们为空?

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 });
}
有帮助吗?

解决方案

它只会按照你的预期工作 如果你是 附着 所创造的 dbTournament 结合上下文。只有在这种情况下,创建集合并准备延迟加载才有意义。但你是 添加dbTournament 作为一个新实体,在这种情况下不能有任何依赖 Round数据库中的 s 可以引用新锦标赛,因此延迟加载查询无论如何都不会返回结果,并且 EF 首先不会为延迟加载创建集合。

可以应用技巧 就像附加 dbTournament 首先和之后将其添加到上下文中。但这只会产生由延迟加载触发的不必要的数据库查询,而没有任何结果,而且相当hacky。在我看来,最简单、最合理的解决方案是默认构造函数中的标准集合初始化......

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);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top