为什么我应该在视图可见所有导航属性时放置.Include(...)
?
动作1
public ActionResult Included(){
var models = db.Money.Include(m=>m.Rate);
return View(models);
}
1动作
public ActionResult UnIncluded(){
var models = db.Money;
return View(models);
}
在两种观点中,我都可以得到如下数额
@Html.DisplayFor(model=>model.Rate.Amount)
那么,有什么区别? 这是我们所知的延迟加载模式吗?
答案 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查询,该查询在Money
和Rate
表之间执行JOIN,以加载1000 Rate
行中每一行的所有Money
数据< em>只进行一次数据库往返。这被称为渴望加载。
As @IronMan84 says,这假设您启用了延迟加载,并且Rate
是virtual
上的Money
导航属性。
答案 1 :(得分:3)
.Include
会强制加载指定的属性,而不是懒惰地加载。因此,在您的第一个操作中,Rate
将立即从数据库中恢复,而不是您的第二个操作,只有在它被调用时才会被带回(再次,假设延迟加载)(即当你在页面上呼叫model.Rate.Amount
时。
您应该注意的一件事:如果您正在使用延迟加载,那么您实际上应该使用.Include
或在控制器操作中使用.ToList()
,因为您可能会运行在您获得异常的情况下,因为您的控制器在之前已经放置了DbContext
对象,因此需要EF返回数据库的导航属性。所以上面的Action1
可能是避免这种情况的更好方法。
Include
{{1}}上的MSDN帖子可以找到here。