当不访问导航属性时,实体框架是延迟加载相关实体

时间:2015-02-19 00:09:58

标签: c# asp.net-mvc entity-framework serialization lazy-loading

我正在尝试使用EF 5(4.4)调试旧版MVC应用程序的性能问题。 SQL Server Profiler显示运行的查询比应该运行的更多。 EF似乎正在为相关模型的每个相关实体生成查询。

现在这听起来像是懒惰加载。问题是,代码中的任何地方都没有引用任何导航属性(至少没有明确地引用)。

当我为上下文关闭延迟加载时,它会修复它。此外,如果我返回模型以外的其他东西(例如视图模型),它会修复它。这是一个旧的,实施不佳的MVC应用程序 - 无论如何它应该使用视图模型,所以这很好。这些都是可接受的修复,但我仍然想知道为什么它正在发生。


我已经读过,在序列化对象时可能会调用导航属性。那是什么发生在这里?如果是这样,你能解释为什么对象被序列化吗? (注意到我对序列化的理解非常基础 - 基本上是here所说的。)


这是一个例子:

控制器

    [HttpGet]
    public ViewResult StoreInfo(int id)
    {
        Store model = _posRepository.GetStore(id);

        return View(model);
    }

存储库

    public Store GetStore(int storeID)
    {
        return _dbContext.Store.Single(x => x.StoreID == storeID);
    }

模型

public partial class Store // highly simplified version
{           
    public int StoreID { get; set; }        
    public string StoreName { get; set; }        
    public Nullable<int> StateID { get; set; }          

    public virtual States State { get; set; } // lazy loaded
}

查看

// blank

2 个答案:

答案 0 :(得分:0)

我发现Glimpse(一个非常有用的ASP.NET诊断工具)是访问其元数据选项卡的导航属性(请参阅我的other question,后者证明是相关的)。直到我禁用延迟加载时,我在nav属性上抛出了NullReferenceException,并检查了我发现它来自Glimpse的调用堆栈。由于EF模型直接传递给视图而不是视图模型,因此在填充元数据时,它正在访问导航属性,从而导致数据库查询。当我禁用Glimpse的元数据选项卡时,它解决了这个问题。

答案 1 :(得分:0)

没有任何第三方使用,您可以通过匿名对象来实现。

var dataList = _dbContext.Store.Single(x => x.StoreID == storeID); var jsonData = dataList.Select(c => new {c.StoreID,c.StoreName,c.StateID,StateName = c.State?.Name,StateCode = c.State?.Code});

返回Json(jsonData,JsonRequestBehavior.AllowGet);

现在希望一切都好