LINQ如何在using语句中延迟执行

想象一下,我有以下几点:

private IEnumerable MyFunc(parameter a) { using(MyDataContext dc = new MyDataContext) { return dc.tablename.Select(row => row.parameter == a); } } private void UsingFunc() { var result = MyFunc(new a()); foreach(var row in result) { //Do something } } 

根据文档,linq执行将推迟直到我实际枚举结果,该结果发生在foreach的行中。 但是,using语句应强制在MyFunct()调用结束时可靠地收集对象。

实际发生了什么,处理器何时运行和/或结果运行?

我唯一能想到的是延迟执行是在编译时计算的,所以实际的调用由编译器移动到foreach的第一行,导致使用正确执行,但直到foreach行才运行? 有没有可以提供帮助的古茹?

编辑: 注意:此代码确实有效,我只是不明白如何。

我做了一些阅读,我在我的代码中意识到我已经调用了ToList()扩展方法,当然这个方法枚举了结果。 勾选答案的行为对于回答的实际问题是完全正确的。

对不起任何困惑。

我希望这根本不起作用; Select是延迟的,因此此时没有消耗任何数据。 但是,由于您已经处理了数据上下文(在离开MyFunc之前),它将永远无法获取数据。 更好的选择是将数据上下文传递给方法,以便消费者可以选择生命周期。 此外,我建议返回IQueryable以便消费者可以“组合”结果(即添加OrderBy / Skip / Take / Where等,并使其影响最终查询):

 // this could also be an instance method on the data-context internal static IQueryable MyFunc( this MyDataContext dc, parameter a) { return dc.tablename.Where(row => row.parameter == a); } private void UsingFunc() { using(MyDataContext dc = new MyDataContext()) { var result = dc.MyFunc(new a()); foreach(var row in result) { //Do something } } } 

更新:如果您(注释)不想延迟执行(即您不希望调用者处理数据上下文),那么您需要评估结果。 您可以通过在结果上调用.ToList().ToArray()来缓冲值。

 private IEnumerable MyFunc(parameter a) { using(MyDataContext dc = new MyDataContext) { // or ToList() etc return dc.tablename.Where(row => row.parameter == a).ToArray(); } } 

如果你想在这种情况下延迟它,那么你需要使用“迭代器块”:

 private IEnumerable MyFunc(parameter a) { using(MyDataContext dc = new MyDataContext) { foreach(SomeType row in dc .tablename.Where(row => row.parameter == a)) { yield return row; } } } 

现在推迟了,而没有传递数据上下文。

我刚刚在这里发布了另一个针对此问题的延迟执行解决方案,包括以下示例代码:

 IQueryable MyFunc(string myValue) { return from dc in new MyDataContext().Use() from row in dc.MyTable where row.MyField == myValue select row; } void UsingFunc() { var result = MyFunc("MyValue").OrderBy(row => row.SortOrder); foreach(var row in result) { //Do something } } 

Use()扩展方法本质上就像延迟using块一样。