【问题标题】:Why is not Entity Framework initializing my navigation collections?为什么实体框架不初始化我的导航集合?
【发布时间】:2014-01-29 09:46:38
【问题描述】:

我正在创建一个 ASP.NET MVC4 锦标赛管理系统,它作为包含类 TournamentRound 对象的集合。我是 EF Code First 的新手,但我知道 EF 是 supposed to initialize 我的集合对象,在实例化时具有观察到的代理类,只要我将它们声明为虚拟。当我尝试在下面的代码中从 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 });
}

【问题讨论】:

标签: asp.net-mvc entity-framework ef-code-first entity-framework-5


【解决方案1】:

它只会像你期望的那样工作 if you were attaching 创建的 dbTournament 到上下文中。只有在这种情况下,创建集合并为延迟加载做准备才有意义。但是您正在添加 dbTournament 作为新实体,在这种情况下,数据库中不能有任何可以引用新锦标赛的依赖 Rounds,因此是延迟加载查询无论如何都不会返回结果,并且 EF 不会首先为延迟加载创建集合。

could apply tricks 喜欢先附加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);
}

【讨论】:

  • 如果我在构造函数中初始化 HashSet,这不会妨碍稍后阅读时的 更改跟踪代理,正如 Rowan Miller 在这个 SO-answer 中所引用的那样? stackoverflow.com/a/4069727/507339 。为了安全起见,我要去InitializeDefaults 的警卫队。作为旁注,我觉得实体框架的这部分文档记录不充分(或者我没有找到)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多