IEnumerable与ToList直接在视图中进行迭代

时间:2015-12-16 09:15:52

标签: c# entity-framework

如果我只需要使用结果一次,即在视图中迭代和显示。我通常会做第一个,是否更明智?

IEnumerable<model> result = _someService.GetValues();
return View(result);

OR

IList<model> result = _someService.GetValues().ToList();
return View(result);

我检查了探查器,并且使用EF6仅对该数据查询了一次db。

要清除它的普通SELECT并且两者都有数据,并且没有相邻列表可以进行延迟加载。

注意:我知道IEnumerable有一个方法GetEnumerator,每当它调用它执行数据时执行,而ToList()只执行一次。

1 个答案:

答案 0 :(得分:3)

请参阅Programmers.SE: Why should I use List<T> over IEnumerable<T>?

  

有时,在linq查询上执行ToList()非常重要,可以确保您的查询按照您期望的顺序执行。

这就是这种情况。

如果_someService.GetValues()通过延迟执行返回IEnumerable<model>这是一个实体框架查询,则在控制器中调用ToList()将在那里执行查询:在您的控制器中,您可以在其中处理可能发生的异常。例如查询超时。

如果您不打电话给.ToList(),则会在您的视图中@foreach (var item in Model)处抛出相同的异常。你不想要那个。

此外,如果您使用延迟加载,则在查询结果在您的视图中结束并再次抛出异常时将处理上下文,因此在这种情况下,您 通过调用.ToList()来实现控制器中的查询结果。

当涉及到IEnumerable<T>IList<T>时,人们会在树中高高举起。他们通常会从一些一般性建议(找到here, amongst others)中互相鹦鹉学舌,但他们不明白该建议是针对 API设计。您没有设计API,您正在实现具有非常特定要求的应用程序:视图可能永远不会抛出异常。为了满足该要求,您必须在控制器中执行查询,因此在那里调用.ToList()

用户询问上面链接的问题是正确的the comment they posted

  

应执行所有查询,以便为视图完成并加载模型。即视图应该接收所有内容而不是查询数据库。

将模型渲染到视图中的剃刀可能没有任何副作用。执行查询是一种副作用,因此在渲染视图时可能不会发生。

即使在控制器中调用.ToList(),视图中的@model指令也可以而且应该仍为IEnumerable<T>