如果我只需要使用结果一次,即在视图中迭代和显示。我通常会做第一个,是否更明智?
IEnumerable<model> result = _someService.GetValues();
return View(result);
OR
IList<model> result = _someService.GetValues().ToList();
return View(result);
我检查了探查器,并且使用EF6仅对该数据查询了一次db。
要清除它的普通SELECT并且两者都有数据,并且没有相邻列表可以进行延迟加载。
注意:我知道IEnumerable有一个方法GetEnumerator,每当它调用它执行数据时执行,而ToList()只执行一次。
答案 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>
!