【问题标题】:DbContext bug? Navigation properties null after retrieving newly saved recordDbContext 错误?检索新保存的记录后导航属性为空
【发布时间】:2012-12-01 01:25:53
【问题描述】:

我的 ASP.NET MVC 4 应用程序使用 Entity Framework v5、Ninject 和 Ninject.MVC3 nuget 包,并且数据存储在 SQL Server Express 中。模型是使用“EF 5.x DbContext Generator for C#”模板生成的。 Lazy Loading Enabled 在我的 edmx 中设置为 True。

我正在使用存储库模式,我的存储库和上下文位于解决方案中的一个单独项目中,该项目被 ASP.NET MVC 4 项目引用。

所以,问题是——在保存了一个新对象(“交易”),它是视图模型的一个属性之后,我查询该对象的存储库。那时,我希望填充的导航属性为空。请参阅下面 Create() 方法中的注释。

如果我从数据库中检索现有交易(我不只是保存的交易),所有导航属性似乎都已填充。

我在this page 上发现了类似/相同问题的报告。文章作者表示,“我认为这是 DbContext 中的一个小故障。即,外键导航属性的延迟加载不适用于新添加的项目,但许多端导航属性的延迟加载有效很好,例如 Teacher.Classes。此故障仅发生在新添加的项目上。如果您没有为新添加的项目在上面显式加载 Class.Teacher,则如果它尚未在实体框架中的某处加载,它将为 null . 但是,如果它已经加载到某个地方,那么 C.Teacher 可以由 Entity Framework 自动解析。而对于 ObjectContext,延迟加载适用于所有类型的导航属性。"

我的控制器的 Create 方法如下所示:

[HttpPost]
public ActionResult Create(TradeViewModel tradeViewModel)
{
    if (ModelState.IsValid)
    {
        _employeesRepository.SaveTrade(tradeViewModel.Trade);
        var trade =
            _employeesRepository.Trades.First(
                x =>
                x.RequesterId == tradeViewModel.Trade.RequesterId &&
                x.RequesterWorkDate == tradeViewModel.Trade.RequesterWorkDate);

        // Null reference encountered below, as trade.TradeType and trade.Employee are both null
        String userMessage = "New " + trade.TradeType.TradeTypeDescription + " requested with '" + ControllerHelpers.GetDisplayName(trade.Employee) + "'";
        TempData["UserMessage"] = userMessage;

        return RedirectToAction("Index");
    }
    return View();
}

员工存储库中的 SaveTrade() 方法如下所示:

public void SaveTrade(Trade trade)
{
    var data = (from t in _context.Trades
                where t.RequesterId == trade.RequesterId
                      && t.RequesterWorkDate == trade.RequesterWorkDate
                select t);
    if (!data.Any())
    {
        _context.Trades.Add(trade);
    }
    _context.SaveChanges();
}

最后,_employeesRepository 的交易看起来像:

public IQueryable<Trade> Trades
{
    get { return _context.Trades; }
}

【问题讨论】:

    标签: asp.net-mvc entity-framework ninject lazy-loading repository-pattern


    【解决方案1】:

    EF 的延迟加载可能会导致此问题。尝试像下面这样急切地加载员工

      var trade =
            _employeesRepository.Trades.Include("TradeType").Include("Employee").First(
         x =>
                x.RequesterId == tradeViewModel.Trade.RequesterId &&
                x.RequesterWorkDate == tradeViewModel.Trade.RequesterWorkDate);
    

    如果您尝试查看由 EF 生成的查询,您可以获得更清晰的图片。我会使用 EfProfiler http://www.hibernatingrhinos.com/products/EFProf 进行此类分析。您当然可以使用自己喜欢的工具。

    希望这会有所帮助。

    更新

    这里是 Julie Lerman 文章的链接,可能有助于理解延迟加载概念http://msdn.microsoft.com/en-us/magazine/hh205756.aspx

    在包含中添加了贸易类型

    【讨论】:

    • An article 我发现说,“我认为这是 DbContext 中的一个故障。即,外键导航属性的延迟加载不适用于新添加的项目,但延迟加载多端的导航属性工作正常,例如 Teacher.Classes。此故障仅发生在新添加的项目中。我很惊讶似乎很少有人遇到这个问题。
    • 好文章.. 它生成什么查询?即使在急切地加载这些连接之后,它也不会创建正确的连接?
    • 我的一位同事遇到了类似的问题,看起来 _context.refresh() 为他解决了这个问题。
    • 急切加载确实可以正常工作(如果我将延迟加载启用为 false,并在 _employesRepository.Trades 中添加 .Include() 语句)。这是我遇到问题的默认,延迟加载启用 = true 设置。 DbContext 中没有 Refresh();我在保存方法结束时尝试了this method,但没有帮助(检索保存的交易后导航属性仍然​​为空)。
    • @Yogiraj:天啊天啊天啊天啊!我的问题解决了!!!非常感谢您的文章和帖子。我有同样的问题2周了。我启用了延迟加载,但我决定“强制”一个 Eager Load.... 它现在正在工作 :D :D :D Woooohoooooo!
    【解决方案2】:

    您可能正在使用New() 创建交易。您应该改用 DBContext 的 Trades.Create() 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多