2010-12-10 56 views
6

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

例如,这quesiton显示Linq2Excel:

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

但什么是比 “天真” 的实施为IEnumerable好处?

+0

不确定为什么linq-to-excel从IQueryable中获利,但有些情况会使代码更快。 – CodesInChaos 2010-12-10 16:41:06

回答

11

Linq提供程序的目的是基本上将Linq表达式树(它们构建在查询的后面)转换为数据源的本地查询语言。在数据已经在内存中的情况下,您不需要Linq提供程序; Linq 2对象很好。但是,如果您正在使用Linq与外部数据存储(如DBMS或云)进行对话,则这是绝对必要的。

任何查询结构的基本前提是数据源的引擎应该尽可能地做大量的工作,并且只返回客户端需要的数据。这是因为数据源被假定为最好地知道如何管理其存储的数据,并且因为数据的网络传输在时间上相对昂贵,因此应该最小化。现在,实际上,第二部分是“仅返回客户请求的数据”;服务器不能读取你的程序的头脑,并知道它真的需要什么;它只能提供它的要求。这是一个智能的Linq提供者绝对会吹走一个“天真”的实现。使用生成表达式树的Linq的IQueryable端,Linq提供者可以将表达式树转换成SQL语句,DBMS将使用该语句返回客户端在Linq语句中要求的记录。一个幼稚的实现需要使用一些广泛的SQL语句来检索所有记录,以便向客户端提供内存对象列表,然后所有的筛选,分组,排序等工作都由客户端完成。

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

7

如果你只是想为你的目的使用LINQ-to-Objects(即类似foreach)的功能,那么你不需要编写LINQ提供程序,它主要针对内存列表。

需要编写一个LINQ提供程序,如果你想分析查询的表达式树,以便将它翻译成别的东西,比如SQL。例如,您提到的ExcelQueryFactory似乎可以与OLEDB-Connection一起使用。这可能意味着在查询数据时不需要将整个excel文件加载到内存中。

3

总体表现。如果你有某种索引,你可以比简单的IEnumerable<T>更快地进行查询。

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

但也有更简单的情况下,它可以是太有用:

如果你有一棵树指数在属性格式Time然后像.Where(x=>(x.Time>=now)&&(x.Time<=tomorrow))范围查询可以优化了很多,并不需要遍历枚举中的每一项。

1

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

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

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

如果我们不相信我们可以使用var关键字和动态它将初始化一个最合适的类型。

相关问题