使用查询表达式与 Seq 模块?

Using query expression vs Seq modules?

在操作通过 FSharp.Data.SqlClient 检索的数据时,使用查询表达式优于 Sequence 模块是否有任何优势?

例如:

query{
    for row in SelectAllCategories.Execute() do
    where row.Id = 1
    select {
        Id = row.Id;
        Category = row.CategoryName
    }
}

对比

SelectAllCategories.Execute()
|> Seq.filter (fun x -> x.Id = 1)
|> Seq.map (fun x ->
                {
                   Id = x.Id;
                   Category = x.CategoryName
                }

就此而言,您甚至可以考虑使用 LINQ。那么有什么优势,特别是关于 FSharp.Data.SqlClient?

查询构建器提供了一种在 F# 中构建 IQueryables 的方法,Seq 模块函数在 IEnumerables 上工作(seq 类型是其别名)。这些是通用的 .NET 接口,而不是 F# 的东西,它们之间的区别已经很好地概述了,例如 here.

此外,除了 Seq 模块功能之外,您还拥有 seq 构建器:

seq {
   for row in SelectAllCategories.Execute() do 
       if row.Id = 1 then 
           yield { Id = row.Id; Category = row.CategoryName }
}

它大致等同于使用 Seq 模块函数,因此选择一个而不是另一个主要是一种风格或方便的决定。

在这种特殊情况下,FSharp.Data.SqlClient 提供默认的 IEnumerable<ProvidedType>.Record 结果类型,而不是任何类型的 IQueryable<ProvidedType>。所有与 SQL 引擎的通信对查询表达式都是不透明的,被封装到提供的 SqlCommandProvider.Execute() 方法中。因此,query {...} 使用 Linq-to-Sql 的任何潜在好处在这里都没有发挥作用。

因此,与查询表达式关联的底层脱糖机制相比,Seq 模块中的函数会产生更好的性能和更少的开销,我不会感到惊讶。在这里使用查询表达式没有任何优势。