LINQ学习笔记:选取Select(4)

http://www.itjxue.com  2015-07-17 01:59  来源:未知  点击次数: 

外部迭代变量

在我们前面的例子中,fullName在SelectMany之后变成了一个外部迭代变量. 这个外部迭代变量依然在可用范围内直到查询结束或者到达一个into从句:

   1: IEnumerable<string> query =
   2:  
   3:   from fullName in fullNames        // 外部变量
   4:  
   5:   from name in fullName.Split( )    // 迭代变量
   6:  
   7:   select name + ” came from “ + fullName;
   8:  
   9: Anne came from Anne Williams
  10:  
  11: Williams came from Anne Williams
  12:  
  13: John came from John Fred Smith

 

如果要使用Lambda语法的话,尤其在有where或者orderby的情况下,会更加复杂一点,这里有一个技巧:

   1: from fullName in fullNames
   2:  
   3: from x in
   4:  
   5:   fullName.Split( )
   6:  
   7:           .Select (name => new { name, fullName } )
   8:  
   9: orderby x.fullName, x.name
  10:  
  11: select x.name + ” came from “ + x.fullName;

 

我们使用了一个匿名类型来搭载临时数据,类似let从句的作用.最后我们可以得到一个完整的Lambda语法的查询:

   1: IEnumerable<string> query = fullNames
   2:  
   3:   .SelectMany (fName =>
   4:  
   5:      fName.Split( )
   6:  
   7:           .Select (name => new { name, fName } ))
   8:  
   9: .OrderBy (x => x.fName)
  10:  
  11: .ThenBy (x => x.name)
  12:  
  13: .Select (x => x.name + ” came from “ + x.fName);

 

复合查询的思考

正如我们前面看到的例子,如果我们需要外部迭代变量, 那么使用复合语法是一个很好的选择,因为它的语义让你可以更加直观的思考.

编写额外的生成器主要有两个基础的模式, 第一个是扩展和平整结果,为了做到这一点,我们可以通过调用已有查询变量的属性或者方法来完成,上面的例子我们就使用了这个方法.

在LINQ to SQL中一个类似的查询就是当你扩展关联的子属性,以下的实例列出了所有的客户和他们对应的采购单:

   1: IEnumerable<string> query =
   2:  
   3:   from c in dataContext.Customers
   4:  
   5:   from p in c.Purchases
   6:  
   7:   select c.Name + ” bought a “ + p.Description;
   8:  
   9: Tom bought a Bike
  10:  
  11: Tom bought a Holiday
  12:  
  13: Dick bought a Phone
  14:  
  15: Harry bought a Car

 

另外一个模式就是执行一个交叉连接,为了做到这一点, 我们的selector表达式返回的将会是一个序列而不是一个迭代变量了:

   1: int[] numbers = { 1, 2, 3 };
   2:  
   3: string[] letters = { “a”, “b” };
   4:  
   5: IEnumerable<string> query = from n in numbers
   6:  
   7:                             from l in letters
   8:  
   9:                             select n.ToString( ) + l;
  10:  
  11: RESULT: { “1a”, “1b”, “2a”, “2b”, “3a”, “3b” }

 

这种风格的查询就是SelectMany风格关联的基础.

使用SelectMany做关联

我们可以使用SelectMany,并通过过滤一个交叉结果集来关联两个序列.例如, 假设我们要安排一场比赛的选手对决, 我们使用以下的查询:

   1: string[] players = { “Tom”, “Jay”, “Mary” };
   2:  
   3: IEnumerable<string> query =
   4:  
   5:   from name1 in players
   6:  
   7:   from name2 in players
   8:  
   9:   select name1 + ” vs “ + name2;
  10:  
  11: RESULT: {“Tom vs Tom”, “Tom vs Jay”, “Tom vs Mary”,
  12:  
  13:          “Jay vs Tom”, “Jay vs Jay”, “Jay vs Mary”,
  14:  
  15:          “Mary vs Tom”, “Mary vs Jay”, “Mary vs Mary”}

 

但这并非我们期望的结果,很明显,选手自己并不需要与自己比赛,因此我们必须要过滤这些不符合条件的输出元素:

   1: IEnumerable<string> query =
   2:  
   3:   from name1 in players
   4:  
   5:   from name2 in players
   6:  
   7:   where name1.CompareTo (name2) > 0
   8:  
   9:   orderby name1, name2
  10:  
  11:   select name1 + ” vs “ + name2;
  12:  
  13: RESULT: { “Jay vs Mary”, “Jay vs Tom”, “Mary vs Tom” }

 

此过滤断言构成了连接条件,我们的查询可以被称为非等连接,因为连接条件没有使用等式操作符.

(责任编辑:IT教学网)

更多

推荐ASP.NET教程文章