使用LinqToSql返回数据库记录?

时间:2012-02-17 08:03:58

标签: c# sql-server-2008 linq-to-sql

我在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。

我对这个场景有两个问题:

  1. 上述产量返回是否真的可以节省资源,并且比将所有记录缓存到数组(.ToArray())更快?

  2. 如果消费方法的using循环内发生错误,或者如果消费方法会破坏数据连接,那么数据连接是否会自动正确关闭(我的意思是foreach语句) foreach循环在中间(如找到所需记录和break)?

3 个答案:

答案 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)

  1. 迭代器将被懒惰地评估。它将拉出第一个项目,然后将其“收益”给消费者。性能影响将取决于LinqDataContext的实现方式(它可能在内部缓存内容)。使用ToArray()或ToList()将强制所有元素退出LinqDataContext,然后再继续。因此,在LinqDataContext返回每个元素之前,使用ToArray()将使您不产生任何内容。无论这是否最佳,取决于您。
  2. 是的,“使用”将被正确执行。