• from 子句
  • where 子句
  • select子句
  • group 子句
  • into 子句
  • orderby 子句
  • join 子句
  • let 子句

复合from子句

  • 在某些情况下,源序列中的每个元素本身可能是序列(集合),也可能包含序列
  • 用语访问单个数据库中的内部集合
  • 使用多个from字句执行连接
  • 可以包含多个可从独立数据源生成补充查询的from字句

复合(顾名思义就是有多from的字句)实例:

class Program
{
    static void Main(string[] args)
    {
        List<Student> students = new List<Student>
		{
			new Student
			{
				LastName = "xiaogui",
				Scores = new List<int> { 97, 42, 91, 60 }
			},
			new Student
			{
				LastName = "xiaozhan",
				Scores = new List<int>{ 50, 92, 81, 60 }
			},
			new Student
			{
				LastName = "xiaolan",
				Scores = new List<int>{ 32, 32, 81, 90 }
			},
			new Student
			{
				LastName = "xiaowan",
				Scores = new List<int>{ 92, 22, 81, 60 }
			},
        };
        var query = from stuent in students
					from score in stuent.Scores
					where score > 90
					select new
					{
						Last = stuent.LastName,
						score
					};
        foreach (var student in query)//大于90分的显示出来        
		{
			Console.WriteLine("{0} Score:{1}", student.Last, student.score);
		}
		Console.ReadLine();
    }
}

public class Student
{
    public string LastName { get; set; }
    public List<int> Scores { get; set; }
}
public class Employee
{
	public string First { get; set; }
	public string Last { get; set; }
	public int ID { get; set; }
}

执行结果:

xiaogui Score:97 xiaogui Score:91 xiaozhan Score:92 xiaowan Score:92

let 关键字(使用let字句扩展范围变量)

  • 创建一个可以查询自身的可枚举类型
  • 使查询只能对范围变量word调用一次ToLower。

如果不使用let,则必须在where字句的每个谓词中调用ToLower

例:把每个单词开头包含a或者e的找出来

using System;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        string[] strings = { "A penny saved is a penny earned.", "The aaxly sdj", "the pa is no" };

        var query = from sentence in strings
                    let words = sentence.Split(' ')//用空格分割成数组                
                    from word in words
                    let w = word.ToLower()//把每个字母小写        
                    where w[0] == 'a' || w[0] == 'e'
                    select word;

        foreach (var s in query)
        {
            Console.WriteLine(s);
        }
        Console.ReadLine();
    }
}

where 关键字 (筛选)

  • 一个查询表达式可以包含多个where字句

例:(把包含a的找出来)

using System;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        string[] str = { "a", "b", "c" };

        var query = from s in str
                    where s == "a"
                    select s;

        foreach (var s in query)
        {
            Console.WriteLine(s);
        }
        Console.ReadLine();
    }
}

orderby 关键字 (排序)

  • 在查询表达式中,orderby字句可以使返回的序列(组)按升序或降序。
  • 可以指定多个键,以便执行一个或多个次要排序操作
  • 默认排序顺序为升序
  • 编译时,orderby字句被转换为对OrderBy方法的调用。orderby字句中的多个键被转换为ThenBy方法调用

descending 降序

ascending 升序

例1:升序

using System;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        string[] str = { "a", "b", "c" };
        var query = from s in str
                    orderby s ascending
                    select s;
    }
}

结果为: a b c

例2:降序

using System;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        string[] str = { "a", "b", "c" }; 
        var query = from s in str 
                    orderby s descending 
                    select s;
    }
}

结果为: c b a

group 关键字 (分组)

  • group 字句返回一个IGrouping(TKey,Telement)对象序列
  • 编译时,group子句被转换为对GroupBy方法的调用

(LINQ查询表达式可以以select或者Group结束) (如果想要对每个组执行附加查询操作,则可以使用into上下文关键字指定一个临时标识符,使用into时,必须继续编写该查询,并最终用一个select语句或另一 个group子句结束该查询)

例:

using System;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        string[] str = { "aa", "bb", "cc", "dd" };
        var query = from s in str
                    group s by s[0]
                        into p
                        where p.Key == 'a' || p.Key == 'b' || p.Key == 'c'
                        orderby p.Key descending
                        select p.Key;

        foreach (var s in query)
        {
            Console.WriteLine(s);
        }
        Console.ReadLine();
    }
}

结果为: c b a

说明: group s by s[0] into p 意思是针对范围变量s用“s[0]”分组,本例中是用第一个字母分组

join 关键字 (联接)

  • 使用join 子句可以将来自不同源序列并且在对象模型中没有直接关系的元素相关联
  • 唯一的要求是每个源中的元素需要共享某个可以进行比较以判断是否相等的值
  • join字句使用特殊的equals关键字比较指定的键是否相等

三中常见的连接类型

  • 内部联接
  • 分组联接
  • 左外部联接

1. 内部联接

var query = from a in str
            join b in str2 on a.id equals b.id
            select new { Aname = a.name, Bname = b.name };

2. 分组联接:(into 可以将join暂存起来)

var query = from a in str 
            join b in str2 on a.id equals b.id into c
            select new { Aname = a.name, Cs = c }

3. 左外部联接

  • 在左外部联接中,将返回左则源序列中所有元素,即使它们在右则序列中没有匹配的元素也是如此。
  • 若要在LINQ中执行左外部联接,请将DefaultifEmpty方法与分组联接结合起来,以指定要在某个左则元素不具有匹配元素时产生的默认右则元素。可以使用null作为任何引

用类型的默认值,也可以指定用户定义的默认类型。

var query = from category in categories 
            join prod in products on category.id equals prod.CategoryID 
            into prodGroup 
            from item prodGroup.defaultifEmpty(new Product{ Name = string.empty, CategoryID = 0 }) 
	    select new { CatName = category.Name, ProdName = item.Name }

equalse 运算符

  • join 子句执行同等联接。换句话说,只能基于两个键之间的相等关系进行匹配
  • 为了表明所有联接都是相等联接,join子句使用equals关键字而不是==运算符

复合键

  • 使用复合键可以测试多个值是否相等

select 关键字

  • 选择输出内容