05/25: Linq (Deferred Execution)ZT
static List<Customer> GetCustomers()
{
return new List<Customer>()
{
new Customer {ID = 1, Name="Bill", Balance = 22.50},
new Customer {ID = 2, Name="Bob", Balance = 0.00},
new Customer {ID = 3, Name="Joe", Balance = -5.00}
};
…..
var Customers = GetCustomers();
string firstLetter = "B";
var ssss = from c in Customers
where c.Name.StartsWith(firstLetter )
select c;
firstLetter = "J";
foreach (Customer cc in ssss)
{
Console.WriteLine(cc.Name);
}
// Result is not Bill and Bob but Joe
Because ssss is a linq referred to firstletter variable.
in code “(Customer cc in ssss) , starting to run with current firstlettter.
是不是所有的linq查询都只是返回IEnumerable<T>?
答案是否定的。
linq的查询在foreach的时候执行,那么,是不是只有当你写出foreach的时候linq才会被执行,没有写出foreach的话linq就一定不会执行,答案显然是否定的。如果你使用一些聚合函数,比如query.First(),query.Max(),linq也会被执行,但是,虽然这个时候你没有写foreach,但聚合函数的执行原理还是用了foreach.
在.net中可以用linq的本地数据源实现的是IEnumerable<T>这个接口。而远程数据源实现的是IQueryable<T>这个接口。
一言以蔽之,本地数据源用IEnumerable<T>,并且查询的逻辑可以直接用你所定义的方法的逻辑(因为有上下文),远程数据源用IQueryable<T>,无法直接使用你所定义的方法的逻辑,必须先生成表达式树,查询由源对象处理。
下面我们再来看一个例子来证明这是两套完全不同的东西:
首先是本地数据源:
List<string> names = new List<string> { "Cai", "Wxied", "Beauty" };
然后我们看看names的where方法
VS的智能提示会告诉我们(sorry,这个地方实在不好截图,大家可以自己尝试,我先给大家描述下)这个扩展方法有2个重载,必须传入Func<T>,返回IEnumerable<T>。
再提一点知识,Func<T>叫谓语表达式,相当于一个委托,我认为,之所以可以直接传Func<T>是因为本地数据源可以直接执行方法的逻辑。
再让我们来看看一个远程数据源:
DataClasses1DataContext dataContext = new DataClasses1DataContext();
dataContext.Customers.Where这个方法有4个重载。必须传入Expression<Func<T>>,返回IQueryable<T>。
大家和上面对比一下,就会发现本地数据源和远程数据源的扩展方法完全不一样,而且远程数据源不能直接传Func<T>,必须用一个 Expression来包装这个Func<T>,正好又从一个方面验证了我们之前所提到的知识。
linq其实有2套东西,用于处理本地数据源的IEnumerable<T>和处理远程数据源的IQueryable<T>。然后本地数据源可以直接代入方法的逻辑进行处理,而远程数据源必须把方法的逻辑变成表达式树,再把表达式树中相应的元素剥离出来,变成远程数据源可以识别的逻辑进行处理,远程数据源要这么做是因为没有了.net运行时这个上下文的支持,所以无法识别.net中的方法的逻辑。
0 Comments:
Post a Comment
<< Home