我在DAL中有一个供应方法:
public IEnumerable<RecordType> GetRecords()
{
using (LinqDataContext context = new LinqDataContext())
{
var records = context.RecordTable;
foreach (RecordType record in records)
{
yield return record;
}
}
}
使用者方法使用foreach
循环中的记录。这样我想通过不缓存来自RecordTable
的所有记录来节省内存使用量,因为LinqToSql在场景后面使用了DataReader。
我对这个场景有两个问题:
上述产量返回是否真的可以节省资源,并且比将所有记录缓存到数组(.ToArray())更快?
如果消费方法的using
循环内发生错误,或者如果消费方法会破坏数据连接,那么数据连接是否会自动正确关闭(我的意思是foreach
语句) foreach
循环在中间(如找到所需记录和break
)?
答案 0 :(得分:3)
1)yield
获取所有值的速度不一定快,但它允许代码在数据库返回所有结果之前开始处理结果。也就是说,yield会在它出现的瞬间返回第一个结果,而ToArray()需要等待所有结果在返回之前显示。当然,如果底层提供商由于缓冲或其他原因立即返回所有结果,这可能没有什么区别。
2)是的,无论你如何退出使用块,using
都会处理LinqDataContext(例外/ return / break /...)
答案 1 :(得分:3)
在执行基本查询的情况下,可以以这种方式工作(当然可以) - 但是,在查询裸Table<T>
的情况下,它可能是它首先缓冲;您可以尝试在迭代期间查询计数或运行跟踪。在这种情况下,我怀疑它将首先缓冲。
重新关闭:这也取决于; p如果有人使用foreach
,那么是:因为foreach
通过finally
显式处理迭代器。然而!例如,如果有人这样做(非常顽皮和松懈),则无法保证:
var iter = yourData.GetEnumerator();
if(iter.MoveNext()) {
Console.WriteLine(iter.Current.Name); // first record of, say, 20
}
// and don't dispose the iterator == bad
然后因为迭代器没有:得到处理,b:耗尽自己,而c:不会崩溃,它不会正常关闭(这三个条件中的任何一个将关闭它正确)。重点:这是一个病态案例:通常说“它会关闭,是的”是合理安全的。
如果您希望保证非缓冲,请注意“精致”具有此功能,如果您将buffered
设置为false
:
IEnumerable<Customer> customers = connection.Query<Customer>(
"select * from Customer", buffered: false);
(它也可以处理参数等)
答案 2 :(得分:2)