【问题标题】:Is looping through IQueryable the same as looping through a Datareader with Reader.Read() in C#通过 IQueryable 循环与在 C# 中使用 Reader.Read() 循环通过 Datareader 相同
【发布时间】:2014-04-27 02:35:43
【问题描述】:

抱歉,标题太长了:)

我真的找不到任何答案,这个问题已经在我脑海中盘旋了一段时间。最后是问题的简短摘要。

基本上,我想知道 linq 到实体/sql 是否在将结果集映射到实体/sql 类之一之前循环通过数据读取器,或者它是否已经映射。在我可以循环通过 Iqueryable 之前,Iqueryable 是否必须循环通过数据读取器。为了显示我在代码中的意思,我想知道是否

foreach(object o in SomeIQueryableObject)
{
    ...do stuff with the object
}

将导致 A:

 while(Reader.Read())
{
     SomeIqueryableObject.Add(Reader.TranslateRow());
}
//now the iqueryable has been loaded with objects and we can loop through it
//with the above code
foreach(object o in SomeIQueryableObject)
{
    ...do stuff with the object
}

还是会导致B:

while(Reader.Read())
{
    ...do stuff with the object
}
//Iqueryable doesn't have to loop through Reader
//before you can loop through Iqueryable.

简短的总结:当我在 iqueryable 上使用 foreach 时,这是否相当于使用 Reader.Read() 遍历数据读取器

【问题讨论】:

    标签: c# sql linq entity-framework linq-to-sql


    【解决方案1】:

    恐怕这里的正确答案是:视情况而定。

    首先 - 这取决于我们正在谈论的IQueryable 实现的类型; IQueryable<T> 只是一个接口,实际的实现留给实现者。据我所知,Microsoft 没有提供任何关于如何完成此操作的严格指南(见鬼,没有人说 IQueryable<T> 需要与数据库有任何共同点,这会使问题变得毫无意义)。

    当我们将自己限制在 linq-to-sql/entity-framework 时,答案仍然是:这取决于(至少对于 linq-to-sql,但如果 EF 的工作方式大不相同,我会感到惊讶)。这取决于几个因素(例如,您正在执行的查询类型、数据量等)。基本上它的工作方式类似于您的第二个伪代码(即不是一次加载所有数据),但可以使用优化来检索块中的数据/缓冲它,因此在某些情况下,数据库端的查询执行可能比您的枚举(尽管尝试使用它的任何方式都可能是......非平凡的)。

    如果要模拟批量加载版本,请显式调用ToList()/ToArray()(或使用任何其他会导致读取所有数据的方法)。

    【讨论】:

    • 这基本上是因为我想知道是否通过使用 reader.read() 而不是 foreach 循环遍历 Iqueryable (编写速度更快)和我的基本问题,我是否获得了任何显着的性能提升,是当我遍历 Iqueryable 时,它​​是否必须遍历数据集,才能将行转换为 Iqueryable 集合,然后才能遍历 Iqueryable。我们以 db.Entity 中的 from d 为例 select d("select * from Entity" in sql)
    【解决方案2】:

    AFAIK EF 将使用您的第二个选项。我这么说的原因是我已经体验到,当您在循环第一个查询的结果时执行另一个查询时,EF 会打开第二个连接。由于我使用的是事务,并且我禁用了分布式事务,并且第二个打开的连接(当第一个连接仍然打开并被使用时)禁用了当前事务的重用,我的第二个查询抛出了一个异常,说 DTC 是'未启用。

    所以我的结论是:如果您正在执行查询并遍历结果(所以没有.ToList()),那么查询仍在执行,并且连接仍然打开,并且如果 EF 正在使用数据读取器,那么是的,它在从数据读取器读取的循环内。

    【讨论】:

    • 你知道当我使用类似 var first = ((IObjectContextAdapter)db) .ObjectContext .Translate<InterEmployee> (reader) 的东西时它是否会迭代,还是它只是将其转换为 iqueryable,然后我可以用它来迭代数据集?
    猜你喜欢
    • 2012-01-02
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    相关资源
    最近更新 更多