可通过多种方式扩展 LINQ,以允许在 LINQ 模式中查询任何数据源。 数据源可能是数据结构、Web 服务、文件系统或数据库,来举例说明。 LINQ 模式使客户端可以轻松查询启用了 LINQ 查询的数据源,因为查询的语法和模式不会更改。 LINQ 可扩展到这些数据源的方式包括:
在某种类型中实现 IEnumerable<T> 接口,以便可以使用 LINQ 查询该类型的对象。
为您的数据源创建一个实现 IQueryable<T> 接口的提供程序。 实现此接口的提供程序以表达式树的形式接收 LINQ 查询,它可以以自定义方式(例如远程)执行。
为数据源创建一个利用现有 LINQ 技术的提供程序。 此类提供程序不仅支持查询,还可以对用户定义的类型进行插入、更新和删除操作及映射。
本主题讨论这些选项。
如何启用数据源的 LINQ 查询
内存中的数据
可通过两种方式启用内存中数据的 LINQ 查询。 如果数据是实现 IEnumerable<T>的类型,则可以使用 LINQ to Objects 查询数据。 如果无法通过实现 IEnumerable<T> 接口启用类型枚举,可以在该类型中定义 LINQ 标准查询运算符方法,或创建扩展该类型的 LINQ 标准查询运算符方法。 标准查询运算符的自定义实现应使用延迟执行返回结果。
远程数据
启用远程数据源 LINQ 查询的最佳选择是实现 IQueryable<T> 接口。 但是,这与为数据源扩展像 LINQ to SQL 这样的提供程序不同。 Visual Studio 2008 中没有用于将现有 LINQ 技术(如 LINQ to SQL)扩展到其他类型的数据源的提供程序模型。
IQueryable LINQ 提供程序
实现 IQueryable<T> 的 LINQ 提供程序在复杂性上可能会有所不同。 本部分讨论不同级别的复杂性。
不太复杂的 IQueryable
提供程序可能与 Web 服务的单个方法进行交互。 这种类型的提供程序非常具体,因为它需要它处理的查询中的特定信息。 它具有封闭类型系统,可能公开单个结果类型。 大多数查询的执行发生在本地,例如,使用 Enumerable 标准查询运算符的实现。 不太复杂的提供程序可能只检查表示查询的表达式树中的一个方法调用表达式,并允许在其他位置处理查询的剩余逻辑。
IQueryable
中等复杂性的提供程序可能以具有部分表达性查询语言的数据源为目标。 如果它面向 Web 服务,它可能会与 Web 服务的多个方法进行交互,并根据查询构成的问题选择要调用的方法。 中等复杂性的提供程序具有比简单提供程序更丰富的类型系统,但它仍然是固定类型系统。 例如,提供程序可能会公开具有可遍历的一对多关系的类型,但不会为用户定义的类型提供映射技术。
复杂的 IQueryable
提供程序(如 LINQ to SQL 提供程序)可能会将完整的 LINQ 查询翻译为表达性查询语言,例如 SQL。 复杂提供程序比不太复杂的提供程序更常规,因为它可以处理查询中更广泛的问题。 它还具有开放类型系统,因此必须包含广泛的基础结构来映射用户定义的类型。 开发一个复杂的服务提供商需要付出大量的努力。