Asp.net mvc DbContext bug?检索新保存的记录后导航属性为空

Asp.net mvc DbContext bug?检索新保存的记录后导航属性为空,asp.net-mvc,entity-framework,ninject,lazy-loading,repository-pattern,Asp.net Mvc,Entity Framework,Ninject,Lazy Loading,Repository Pattern,我的ASP.NET MVC 4应用程序使用Entity Framework v5、Ninject和Ninject.MVC3 nuget包,数据存储在SQL Server Express中。模型是使用“EF 5.x DbContext Generator for C#”模板生成的。在我的edmx中,已启用延迟加载设置为True 我使用的是repository模式,我的存储库和上下文位于解决方案中一个单独的项目中,该项目由ASP.NET MVC 4项目引用 所以,问题是——在保存了一个新对象(“Tr

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

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

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

如果我从数据库中检索到一个现有的交易(一个我没有保存的交易),所有的导航属性似乎都被填充了

我在上发现了一个类似/相同问题的报告。这篇文章的作者说,“我认为这是DbContext中的一个小故障。也就是说,外键导航属性的延迟加载对新添加的项不起作用,但在许多终端中导航属性的延迟加载效果良好,例如Teacher.Classes。只有新添加的项目才会出现此故障。如果您没有为新添加的项在上面显式地加载Class.Teacher,那么如果没有在实体框架中的某个地方加载它,它将为null。然而,若它已经加载到某个地方,那个么C.Teacher可以由实体框架自动解析。然而,对于ObjectContext,延迟加载适用于所有类型的导航属性。”

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

[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();
}
public IQueryable<Trade> Trades
{
    get { return _context.Trades; }
}
最后,雇员储蓄的交易如下所示:

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();
}
public IQueryable<Trade> Trades
{
    get { return _context.Trades; }
}
publicIQueryable交易
{
获取{return\u context.Trades;}
}

EF的不同加载可能会导致这种情况。请尝试像下面这样急切地加载员工

  var trade =
        _employeesRepository.Trades.Include("TradeType").Include("Employee").First(
     x =>
            x.RequesterId == tradeViewModel.Trade.RequesterId &&
            x.RequesterWorkDate == tradeViewModel.Trade.RequesterWorkDate);
如果您尝试查看EF生成的查询,您可以获得更清晰的图片。我会使用EfProfiler进行此类分析。当然,您可以使用您最喜欢的工具

希望这有帮助

更新

下面是Julie Lerman文章的链接,可能有助于理解延迟加载的概念


在include

中添加了tradetype您可能正在使用
New()
创建交易。您应该使用DBContext的
交易。Create()
方法来代替。

我发现说,“我认为这是DBContext中的一个小故障。也就是说,外键导航属性的延迟加载对新添加的项不起作用,但在许多终端中导航属性的延迟加载效果良好,例如Teacher.Classes。此故障仅出现在新添加的项上。“我只是很惊讶,似乎很少有人遇到此问题。文章不错。它生成了什么查询?即使在急切地加载这些查询之后,它也无法创建正确的联接?我的一位同事遇到了类似的问题,它看起来像_context.refresh()为他解决了这个问题。即时加载确实可以正常工作(如果我将lazy loading enabled设置为false,并在_employesRepository.Trades中添加.Include()语句)。这是我遇到问题的默认设置,lazy loading enabled=true。DbContext中没有Refresh();我在保存方法结束时尝试过,但没有帮助(检索保存的交易后,导航属性仍然为空)。@Yogiraj:OMG OMG OMG OMG OMG OMG OMG OMG OMG OMG OMG OMG OMG!!!我的问题解决了!!!非常感谢你的文章和帖子。我已经有两周的时间遇到同样的问题了。我启用了延迟加载,但我决定“强制”一个急切的加载…它正在工作:D:D:D-wooooooooooo!