Language-Integrated Query (LINQ,语言集成查询)是下一代.NET 数据访问技术,它借鉴了很多函数编程的概念,因此,它非常适合 F#。
本质上,LINQ 是一组处理集合的库,它实现操作IEnumerable<T> 接口,在这方面,非常像 F# 的序列(Seq)模块,我们在第七章中讨论过。其核心是通过这些库查询在内存中的集合,它可以是数据库,也可以 XML 文件,还可以是从其他 API 返回的对象。
虽然我们熟悉在 LINQ 库实现的概念,但是,还是与基于 SQL 的命名约定有稍许不同。例如,与Seq.map 等价的叫 Sequence.Select,与 Seq.filter 等价的叫 Sequence.Where。下面的例子演示了如何使用这个类库,第一步是把由 LINQ 库公开的方法导入,形成更可用的形式:
module Strangelights.LinqImports
open System
open System.Linq
open System.Reflection
//define easier access to LINQ methods
let select f s =
Enumerable.Select(s, new
Func<_,_>(f))
let where f s =
Enumerable.Where(s, new
Func<_,_>(f))
let groupBy f s =
Enumerable.GroupBy(s, new
Func<_,_>(f))
let orderBy f s =
Enumerable.OrderBy(s, new
Func<_,_>(f))
let count s =
Enumerable.Count(s)
这些函数一旦导入,就很容易使用,特别是向前管道(|>)运算符。下面的例子这演示这种用法,它使用 LINQ 库查询字符串类,并按照它的非静态方法的重载进行分组:
open System
openStrangelights.LinqImports
//query string methods using functions
let namesByFunction =
(typeof<string>).GetMethods()
|> where (fun m
-> not m.IsStatic)
|> groupBy (fun m
-> m.Name)
|> select (fun m
-> m.Key, count m)
|> orderBy (fun (_, m)
-> m)
//print out the data we‘ve retrieved from about the string class
namesByFunction
|>Seq.iter (fun (name, count)
-> printfn "%s - %i" name count)
运行结果如下:
ToLowerInvariant - 1
TrimEnd - 1
GetHashCode - 1
TrimStart - 1
GetEnumerator - 1
GetType - 1
GetTypeCode - 1
ToUpperInvariant - 1
Clone - 1
CopyTo - 1
get_Length - 1
Insert - 1
get_Chars - 1
PadLeft - 2
CompareTo - 2
PadRight - 2
ToUpper - 2
ToLower - 2
ToString - 2
Trim - 2
Remove - 2
ToCharArray - 2
Substring - 2
IsNormalized – 2
Normalize - 2
Replace - 2
IndexOfAny - 3
EndsWith - 3
Equals - 3
StartsWith - 3
LastIndexOfAny - 3
Split - 6
LastIndexOf - 9
IndexOf – 9
介绍 LINQ