Wednesday, May 26, 2010

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