编写自定义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的“天真”实现的好处是什么?
答案 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关键字并动态地将其初始化为最合适的类型。