为什么要编写自定义LINQ提供程序?

时间:2010-12-10 16:26:29

标签: c# linq linq-to-sql ienumerable

编写自定义LINQ提供程序而不是编写实现IEnumerable的简单类有什么好处?

例如,此quesiton显示Linq2Excel:

var book = new ExcelQueryFactory(@"C:\Users.xls");
var administrators = from x in book.Worksheet<User>()
                     where x.Role == "Administrator"
                     select x;

但是,作为IEnumerable的“天真”实现的好处是什么?

4 个答案:

答案 0 :(得分:13)

Linq提供程序的目的是将Linq表达式树(在查询的幕后构建)基本上“转换”为数据源的本机查询语言。如果数据已经在内存中,则不需要Linq提供程序; Linq 2对象很好。但是,如果您使用Linq与DBMS或云等外部数据存储进行通信,则绝对必要。

任何查询结构的基本前提是数据源的引擎应尽可能多地完成工作,并仅返回客户端所需的数据。这是因为假设数据源最好知道如何管理它存储的数据,并且因为数据的网络传输在时间上相对昂贵,因此应该最小化。现在,实际上,第二部分是“只返回客户要求的数据”;服务器无法读懂您的程序并知道它真正需要什么;它只能提供它的要求。这里是一个聪明的Linq提供商绝对打破了一个“天真”的实现。使用生成表达式树的Linq的IQueryable端,Linq提供程序可以将表达式树转换为,例如,DBMS将用于返回客户端在Linq语句中要求的记录的SQL语句。一个简单的实现需要使用一些广泛的SQL语句检索所有记录,以便向客户端提供内存中对象的列表,然后所有过滤,分组,排序等工作都由客户端完成。 / p>

例如,假设您使用Linq通过其主键从DB中的表中获取记录。 Linq提供程序可以将dataSource.Query<MyObject>().Where(x=>x.Id == 1234).FirstOrDefault()转换为“来自MyObjectTable WHERE Id = 1234的SELECT TOP 1 *”。返回零或一条记录。 “天真”实现可能会向服务器发送查询“SELECT * FROM MyObjectTable”,然后使用Linq的IEnumerable端(用于内存类)进行过滤。在一个声明中,您希望从包含1000万条记录的表中产生0-1结果,您认为哪些可以更快地完成工作(甚至可以完成工作,而不会耗尽内存)?

答案 1 :(得分:7)

如果您只想为了您的目的使用LINQ到对象(即foreach - )功能,那么您不需要编写LINQ提供程序,这主要适用于内存列表。< / p> 如果要分析查询的表达式树,以便将其转换为其他内容(如SQL), 需要编写LINQ提供程序。您提到的ExcelQueryFactory似乎可以使用OLEDB-Connection。这可能意味着在查询数据时不需要将整个excel文件加载到内存中。

答案 2 :(得分:3)

一般表现。如果您有某种索引,则可以比简单IEnumerable<T>上的查询快得多。

Linq-To-Sql就是一个很好的例子。在这里,您将linq语句转换为另一个语句,以供SQL服务器理解。因此,服务器将使用索引进行过滤,排序,...并且不需要将整个表发送到客户端,然后使用linq-to-objects执行它。

但是有一些更简单的情况也可以使用它:

如果您的树索引超过了Time,那么像.Where(x=>(x.Time>=now)&&(x.Time<=tomorrow))这样的范围查询可以进行大量优化,而不需要遍历可枚举中的每个项目。

答案 3 :(得分:1)

LINQ将尽可能提供延迟执行以提高性能。

IEnumurable&LT;&GT;和IQueryable&lt;&gt;将完全提供不同的程序实现。 IQueryable将通过动态构建表达式树来提供本机查询,这提供了良好的性能,然后IEnumurable。

http://msdn.microsoft.com/en-us/vcsharp/ff963710.aspx

如果我们不确定我们是否可以使用var关键字并动态地将其初始化为最合适的类型。