Linq 语法

Linq 是语言集成查询(Language-Integrated Query)的简称,是一系列直接将查询功能集成到 C# 语言的技术统称。Linq 提供了统一种跨数据源和数据格式使用数据的一致模型,并且 Linq 查询支持编译时类型检查和智能提示。
支持 Linq 查询的对象有:

  1. SQL Server Database(Linq to SQL)
  2. XML Document(Linq to XML)
  3. Object Collection(Linq to Objects)
  4. ADO.Net Dataset(Linq to DataSet)
  5. Entity Framework(Linq to Entities)
  6. 实现了 IEnumerable 或 IEnumerable接口的任何对象集合
    定义 Master 和 Dog 实体:
public class Master
{
	public long Id { get; set; }
	public string Name { get; set; }
}
	
public class Dog
{
	public long Id { get; set; }
	public long MasterId { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
}

初始化数据:

Master m1 = new Master { Id = 1, Name = " 小七" };
Master m2 = new Master { Id = 2, Name = " 安" };
Master m3 = new Master { Id = 3, Name = " 小Q" };

Dog d1 = new Dog { Id = 1, MasterId = 1, Name = " 旺财", Age = 3 };
Dog d2 = new Dog { Id = 2, MasterId = 1, Name = " 汪汪", Age = 1 };
Dog d3 = new Dog { Id = 3, MasterId = 2, Name = " 京巴", Age = 5 };
Dog d4 = new Dog { Id = 4, MasterId = 3, Name = " 泰迪", Age = 2 };
Dog d5 = new Dog { Id = 5, MasterId = 3, Name = " 中华田园", Age = 6 };

Master[] masters = { m1, m2, m3 };
Dog[] dogs = { d1, d2, d3, d4, d5 };

其中 masters 和 dogs 就是数据源,因为数组实现了 IEnumerable 接口。

获取数据源

在 Linq 查询中,首先是指定数据源。使用 from 子句引入数据源 masters 并声明范围变量 m

var masterQuery1 = from m in masters
				   select m;

范围变量类似 foreach 循环中的迭代变量,但查询表达式中不会真正发生迭代,当执行查询时,范围变量将充当对 masters 中每个连续元素的引用。而且无需显示指定范围变量的类型,因为编译器可以推断出范围变量的类型。

筛选

筛选器实际指定要从源数据中筛选出哪些元素。并且可以使用 C# 逻辑 ANDOR 运算符,在 where 子句根据需要应用尽可能多的筛选器表达式。

var masterQuery2 = from m in masters
				   where m.Name == "小Q"
				   select m;
				  
// lambda 写法,因为编译后是同一个东西,所以可以混用
var masterQuery3 = (from m in masters select m).Where(m => m.Name == "小Q");

排序

排序通过 orderby 子句,根据要排序类型的默认比较器,对返回序列中的元素排序。

var dogQuery1 = from d in dogs
				where d.MasterId == 3 && d.Id > 3
				orderby d.Name descending
				select d;

var dogQuery2 = dogs.Where(d => d.MasterId == 3 && d.Id > 3).OrderByDescending(d => d.Name);

分组

group 子句根据指定属性的结果进行分组。分组结果以列表的形式展示。列表中每个元素都是具有 key 成员对象,列表中的元素根据该属性被分组。而且在循环访问生成组序列的查询时,必须使用嵌套 foreach 循环,外层循环访问每个组,内层循环访问每个组的成员。

var dogQuery3 = from d in dogs
				where d.Id > 1
				group d by d.MasterId into dogGroup
				where dogGroup.Key >= 2
				orderby dogGroup.Key descending
				select dogGroup;

var dogQuery4 = dogs.Where(d => d.Id > 1).GroupBy(d => d.MasterId)
	.Where(g => g.Key >= 2).OrderByDescending(g => g.Key);
	
foreach (IGrouping<long, Dog> dogGroup in dogQuery3)
{
	foreach (Dog dog in dogGroup)
	{
		Console.WriteLine(dog.Name);
	}
}

联接

联接操作用来在不同范围变量间创建关联,这里范围变量来自不同数据源。在 Linq 中,join 子句始终作用于对象集合,而非直接作用于数据库表。

var dogQuery5 = from d in dogs
				join m in masters on d.MasterId equals m.Id
				select new { DogName = d.Name, MasterName = m.Name };

在 Linq中不用像在 SQL 中频繁使用 join,因为 Linq 中的外键在对象模型中表示为包含项集合的属性。

public class Master
{
	public IEnumerable<Dog> Dogs { get; set; }
}
	
var dogQuery6 = from dog in m1.Dogs select dog;

选择(投影)

select 子句用于指定生成的查询结果,可以是整个对象、其中一个成员、成员的子集,还可以是基于计算或新对象创建的结果类型。如上例的:…… select new { DogName = d.Name, MasterName = m.Name };

延迟加载

在 Linq 中,查询变量本身只存储查询命令,不执行任何操作并且不会返回任何数据。查询实际执行将推迟在 foreach 语句中循环访问查询变量之后进行,也就是在要用到具体数据的时候才会加载到内存中,而不是直接将数据查询出来。这个概念称为延迟加载,又称为懒加载。
对一系列源元素执行聚合函数的查询必须首先循环访问这些元素,如:CountMaxAverageFirst等。由于查询本身必须遍历以返回结果,所以这些查询在执行时不使用显示 foreach 语句。

int masterCount = masterQuery1.Count();

如果要强制立即执行查询并缓存其结果可以通过 ToList 或 ToArray 方法(实际内部也是遍历了查询):

List<Master> master =
	(from m in masters where m.Name == "小Q" select m)
	.ToList();

其他

只有WhereSelectOrderByGroupByJoin等能用 Linq 写法,如果用MaxMinCountAverageSumAnyFirstFistOrDefaultSingleSingleOrDefaultDistinctSkipTake 等则要用 lambda 的写法。
Any() 判断集合是否包含元素,返回值是 bool,效率一般比Count()>0高;
Distinct() 剔除完全重复数据。自定义对象的 Equals 问题:需要重写 Equals 和 GetHashCode 方法来进行内容比较。
OrderBy() 升序、OrderByDescending() 降序、ThenBy() 指定多个排序规则、也支持ThenByDescending()。这些操作不会影响原始的集合数据。
Ship(n) 跳过前面 n 条数据;
Take(n) 获取最多 n 条数据,如果不足 n 条获取全部;
Except(items) 排除当前集合中在 items 中存在的元素;
Union(items) 把当前集合和 items 集合组合;
Intersect(items) 把当前集合和 items 集合取交集;
GroupBy() 分组之后可以使用一些聚合函数:Average()Max()Min()Sum()等;
SelectMany() 把集合中每个对象的集合属性的值重新拼接为一个新的集合;
Join() 可以实现和数据库一样的 Join 效果。

你可能感兴趣的:(Linq)