表达式树不是一段可持行代码,而是一种数据结构
为什么要将LINQ to SQL查询表达式转换成表达式树?
表达式树是一个用来表示可执行代码的数据结构。那我们为什么要将LINQ to SQL查询表达式转换成表达式树呢?
一个LINQ to SQL查询不是在C#程序里执行的,而是被转换成SQL语句,通过网络发送,最后在数据库服务器上执行的。也就是说,下面这个LINQ查询不是在C#程序里执行的。
var query = from c in db.Customers where c.City == "Nantes" select new { c.City, c.CompanyName };
它是被转换成SQL语句后在数据库服务器上运行的。转换后的SQL语句如下代码。
SELECT [t0].[City], [t0].[CompanyName]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[City] = @p0
表达式树是为了更方面地将查询表达式转换成字符串(这里指的是SQL语句)并交给其它程序(这里一般指数据库服务器)执行。
IQueryable<T>和IEnumerable<T>
LINQ to Objects通常返回IEnumerable<T>,而LINQ to SQL返回的是IQueryable<T>
IEnumberable<T>的定义如下
public interface IEnumerable<T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
IQueryable<T>的定义如下:
public interface IQueryable : IEnumerable { Type ElementType { get; } Expression Expression { get; } //表达式树 IQueryProvider Provider { get; } }
IQueryable<T>包含一个Expression表达式树的定义而IEnumberable<T>却没有,这同时也揭示了一个现象,表达式树通常用在LINQ to SQL查询中,而LINQ to Objects中却很少使用。
那为什么LINQ to Objects中很少使用表达式树呢?是因为LINQ to Objects查询通常在.net程序中就可以完成,不需要将其转换成字符串(或SQL语句)发送到其它程序中执行。
那么针对这两种返回类型,我们该怎么选择呢?这里有两条原则可以参考:
- 如果查询表达式可以在本程序里执行的,那么使用Enumberable<T>就可以完成任务。
- 如果查询表达式需要被转换成字符串并发送到其它程序中执行的,那么就应该使用IQueryable<T>和表达式树。