我为什么要使用`.Include(...)`来包含导航属性?

时间:2015-01-06 14:21:34

标签: entity-framework

为什么我应该在视图可见所有导航属性时放置.Include(...)

  1. 动作1

     public ActionResult Included(){
         var models = db.Money.Include(m=>m.Rate);
         return View(models);
     }
    
  2. 1动作

     public ActionResult UnIncluded(){
         var models = db.Money;
         return View(models);
     }
    
  3. 在两种观点中,我都可以得到如下数额

       @Html.DisplayFor(model=>model.Rate.Amount)
    

    那么,有什么区别? 这是我们所知的延迟加载模式吗?

2 个答案:

答案 0 :(得分:4)

  

那么,有什么区别?这是我们所知的延迟加载模式吗?

假设您的Money表有1000行。还假设Rate是导航属性,以下将执行1001个单独的SQL查询:

public ActionResult UnIncluded(){
     var models = db.Money;
     return View(models);
}
...
@Html.DisplayFor(model=>model.Rate.Amount)

为什么呢?上述操作只会将Money数据返回给视图。然后,视图在迭代每个Money实例时,将懒惰地加载每个.Rate实例。这意味着1000个额外的SQL查询,一个用于集合中的每个Money项目。

但是,以下内容仅执行1个SQL查询:

public ActionResult Included(){
     var models = db.Money.Include(m=>m.Rate);
     return View(models);
 }
...
@Html.DisplayFor(model=>model.Rate.Amount)

为什么呢?上述操作将执行单个SQL查询,该查询在MoneyRate表之间执行JOIN,以加载1000 Rate行中每一行的所有Money数据< em>只进行一次数据库往返。这被称为渴望加载。

As @IronMan84 says,这假设您启用了延迟加载,并且Ratevirtual上的Money导航属性。

答案 1 :(得分:3)

假设在应用程序中启用了延迟加载,

.Include会强制加载指定的属性,而不是懒惰地加载。因此,在您的第一个操作中,Rate将立即从数据库中恢复,而不是您的第二个操作,只有在它被调用时才会被带回(再次,假设延迟加载)(即当你在页面上呼叫model.Rate.Amount时。

您应该注意的一件事:如果您正在使用延迟加载,那么您实际上应该使用.Include或在控制器操作中使用.ToList(),因为您可能会运行在您获得异常的情况下,因为您的控制器在之前已经放置了DbContext对象,因此需要EF返回数据库的导航属性。所以上面的Action1可能是避免这种情况的更好方法。

Include {{1}}上的MSDN帖子可以找到here