IQueryable 和 AsEnumerable():延迟执行与立即执行 [重复]

Posted

技术标签:

【中文标题】IQueryable 和 AsEnumerable():延迟执行与立即执行 [重复]【英文标题】:IQueryable and AsEnumerable(): deferred execution vs immediate execution [duplicate] 【发布时间】:2019-12-05 05:56:12 【问题描述】:

AsEnumerable() 可以从GetCars 中删除,而GetCars 仍然是延迟执行吗?

public IEnumerable<Car> GetCars(string id)


  IEnumerable<Car>  cars = IDocumentClient.CreateDocumentQuery<Car>(link).AsEnumerable();

 return cars.Where(r => r.Id == Id);

 

如下:

//GetCars2 is still deferred execution?
public IEnumerable<Car> GetCars2(string Id)


     IOrderedQueryable<Car>  cars = IDocumentClient.CreateDocumentQuery<Car>(link)

     return cars.Where(r => r.Id == .Id);

 

https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.documents.client.documentclient.createdocumentquery?view=azure-dotnet

更新

我希望首先在数据库中完成所有过滤,从而减少返回的数据。

另外,我在调用GetCar() 后进行了更多过滤。使用IEnumerable 允许延迟执行以过滤GetCar() 内部和外部。

可以用IQueryable 代替吗?有什么好处?

GetCars3 中的过滤是否也考虑用于 SQL 查询(GetCar2 和 GetCar3)?因此,这两种方法都会减少从数据库返回的数据?

 public IEnumerable<Car> GetCars3(string Model )
    
       return GetCars2(id).Where(r => r.Model == Model);
     

更新2

mjwills 建议使用 IQueryable 作为 GetCarX() 的返回类型。但我不明白为什么。因为使用 IEnumerable 仍然具有所有好处。也就是说,文件过滤是在数据库端执行的,而不是 C#。如果我错了,请纠正我。

Returning IEnumerable<T> vs. IQueryable<T>

LINQ 提供者:

https://azure.microsoft.com/en-us/blog/azure-documentdb-s-linq-provider-just-got-better/

读取查询: How to construct IQueryable query using Linq when I just need count without reading all documents in Document-Db database?

https://github.com/Azure/azure-cosmos-dotnet-v2/issues/58

How to construct IQueryable query using Linq when I just need count without reading all documents in Document-Db database?

SQL:https://docs.microsoft.com/en-gb/azure/cosmos-db/sql-query-getting-started#linq-to-documentdb-sql

更新 3

本题与AsEnumerable()有关,在定义Where的同一函数中使用,以don't it为例。

它与之前的帖子有细微的差别,在这篇文章中更明确地解释了这一点。

因此,不应将此帖子标记为重复。

【问题讨论】:

添加 AsEnumerable 不会使其“立即执行”。这只是意味着后续过滤等将是客户端(即在 C# 中)。作为一般规则,如果是IQueryable,那么请尽量将其保留在IQueryable 但我认为 CreateDocumentQuery&lt;Car&gt;(link) 在调用 'AsEnumerable()' 之前不会发送查询。 我希望所有的过滤都先在数据库中完成,从而减少返回的数据。 使用AsEnumerable 几乎肯定不会给你任何有用的东西。我建议使用IQueryable。如果GetCars 返回IQueryable,则可以进行进一步过滤(它可以发生在服务器端,而不是在C# 中(如果您使用AsEnumerable,它将在下载所有记录后进行C# 过滤)。 请参阅更新 3 以重新打开帖子。 【参考方案1】:

在您的两个示例中,它们都将使用延迟执行运行 - 在迭代 IQueryableIEnumerable 之前,它们不会将基础查询发送到服务器。

GetCarsGetCars2 之间的区别仅在于,当 GetCars 的结果最终被其调用者枚举时,Where 谓词中的子句将在客户端上运行 - 因为每个结果都在iterable 从服务器经过下来,会被评估返回或丢弃;与GetCars2 相比(如果IQueryable 的具体实现支持它),Where 谓词将被考虑到发送到服务器的查询中。如果从CreateDocumentQuery 返回的IQueryable 的实现不支持方法链来构造查询,那么它们将以相同的方式工作。但无论哪种情况,它们都使用延迟执行,因为在实际枚举方法的结果之前,不会将任何内容发送到服务器。

响应添加到问题的更新 - 将AsEnumerable() 视为门函数。它会切断将与服务器通信的IQueryable 与您在其后添加的任何其他 LINQ 类型方法之间的通信。 IQueryableAsEnumerable 之后发生的事情视而不见。因此,如果您想使用方法链编写服务器端查询,请不要使用AsEnumerable 中断链。

【讨论】:

谢谢。 ***.com/questions/2876616/… 帮助

以上是关于IQueryable 和 AsEnumerable():延迟执行与立即执行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

.AsEnumerable() 和 .ToList() 的区别:

IQueryable和IEnumerable,IList的区别

linq中AsEnumerable和AsQueryable的区别

linq中AsEnumerable和AsQueryable的区别

LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别

AsEnumerable()对LINQ实体的影响是什么?