JK.*_*JK. 7 c# linq asp.net-mvc deferred-execution
给定一个返回MVC视图的非常基本的LINQ,延迟执行在什么时候开始执行?
在控制器中:
public ActionResult Index()
{
var model = _fooService.GetAll();
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
在模型中:
@foreach (var item in Model) {
<tr>
<td>@item.Bar</td>
</tr>
}
Run Code Online (Sandbox Code Playgroud)
当我们调用时,查询不会被执行_fooService.GetAll(),但是会延迟到稍后的某个时间点 - 但是它执行的确切位置是什么?
return View(model);控制器中的语句(看起来不像)?@foreach (var item in Model)视图中的线?@item.Bar看到视图中的线?return View(model);和正在呈现的视图?查询执行(我假设GetAll返回iqueryable)将被延迟到视图中,并将在foreach行上解包,因为这是您开始迭代集合的第一个地方.
更新 对于任何感兴趣的人,这里是"证据".创建一个这样的类:
public class DiagnosticCollection<T> : System.Collections.Generic.List<T>
{
public new Enumerator GetEnumerator()
{
Debug.Print("Collection Unwrap");
return base.GetEnumerator();
}
}
Run Code Online (Sandbox Code Playgroud)
在你的视图中测试它像这样:
@model PlayMvc.Models.DiagnosticCollection<string>
@{System.Diagnostics.Debug.Print("Before foreach");}
@foreach (var item in Model)
{
System.Diagnostics.Debug.Print("After foreach");
@item
}
Run Code Online (Sandbox Code Playgroud)
MSDN 文档在延迟查询执行部分解决了这个问题(重点是我的)。
在返回值序列的查询中,查询变量本身从不保存查询结果,只存储查询命令。查询的执行将被推迟,直到在 foreach 或 For Each 循环中迭代查询变量为止...
这缩小了选项 2 和 3 的答案范围。
foreach只是语法糖,编译器将其重写为 while 循环。这里对这里发生的事情有一个非常全面的解释。基本上你的循环最终会看起来像这样
{
IEnumerator<?> e = ((IEnumerable<?>)Model).GetEnumerator();
try
{
int m; // this is inside the loop in C# 5
while(e.MoveNext())
{
m = (?)e.Current;
// your code goes here
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
枚举器在到达循环内的代码之前是先进的,所以稍微在您到达之前@item.Bar。只剩下选项 2,即该@foreach (var item in Model)行(尽管从技术上讲,在编译器处理完您的代码后该行并不存在)。
如果查询将在调用GetEnumerator()或第一次调用时执行,我不会起诉e.MoveNext()。
正如 @pst 在评论中指出的那样,还有其他方法可以触发查询的执行,例如通过调用ToList,并且它可能不会在内部使用foreach循环。MSDN 文档在这里解决了这个问题:
IQueryable 接口继承了 IEnumerable 接口,因此如果它表示一个查询,则可以枚举该查询的结果。 枚举会导致执行与 IQueryable 对象关联的表达式树。“执行表达式树”的定义特定于查询提供程序。例如,它可能涉及将表达式树转换为底层数据源的适当查询语言。调用 Execute 方法时将执行不返回可枚举结果的查询。
我对此的理解是尝试枚举表达式将导致它执行(无论是通过某种foreach方式还是其他方式)。具体如何发生将取决于提供商的实施。
| 归档时间: |
|
| 查看次数: |
681 次 |
| 最近记录: |