LINQ详解及汇总
LINQ(Language Integrated Query)是微软的一项技术,允许开发者以一种简洁的方式查询和操作数据,支持多种数据源,包括对象、数据库、XML和数据集。LINQ定义了约40个查询操作符,如select、from、in、where以及order by等,这些操作符可以编写查询语句,处理各种类型的数据。
LINQ可以用最少的代码对数据源执行复杂的筛选、排序和分组操作。使用相同的基本查询表达式模式来查询和转换 SQL数据库、ADO.NET数据集、XML文档和流以及,NET集合中的数据。
查询表达式必须以from 子句开头,并且必须以select或group 子句结尾。在第一个 from 子
句和最后一个select或group 子句之间,查询表达式可以包含一个或多个下列可选子句。LINQ查询代码中关键字必须小写。
LINQ的不同实现形式及其现状:
- LINQ to Objects:用于操作内存中的对象集合。
- LINQ to SQL:用于查询数据库。然而,LINQ to SQL已经停止维护,被Entity Framework(EF)取代。
- LINQ to Datasets:用于操作数据集。
- LINQ to Entities:用于查询实体框架中的数据。
- LINQ to XML/XSD:用于操作XML数据。
- LINQ to Data Source:用于查询数据源。
基本步骤
- 创建数据模型:使用 LINQ to SQL 工具自动生成或手动创建与数据库表对应的 C# 类。
- 执行查询:使用 LINQ 查询语法来检索、更新、插入或删除数据。
- 提交更改:将对数据所做的更改同步回数据库。
LINQ数据源
- 应用程序始终将源数据视为一个lEnumerable<T>或IQueryable<T>集合。在 LINQtoXML中,源数据显示为一个IEnumerable<XElement>。
- 在 LINQto DataSet中,它是一个IEnumerable<DataRow>。在 LINQ toSQL中,它是定义用来表示SQL表中数据的任何自定义对象的lEnumerable 或lQueryable。
- (IEnumerable<T> 或 IQueryable<T>:这是大多数LINQ查询的返回值类型。它们表示一个序列,可以包含零个、一个或多个元素。)
LINQ组成部分(大概):
- IEnumerable<T> 枚举器 (详解: C#—内建接口: IEnumerable与IEnumerator接口详解-CSDN博客)
- 扩展方法 : (详解: C#—扩展方法-CSDN博客)
- IQueryable<T> (它实现了IEnumerable) (详解: C#—内建接口: IQueryable接口详解-CSDN博客)
- lambda表达式 :(详解: C#之lambda表达式_c# array.exists-CSDN博客)
LINQ语法:
一、select 查询
// 扩展方法 Select
var query = studentsList.Select(s => new { id = s.Id, age = s.Age > 20 ? 20 : 0 }); // new { id = s.Id, age20 } // 匿名实例
// 表达式用法 Select
var query2 = from s in studentsList select new { id = s.Id, age = s.Age > 20 ? 20 : 0 };
二、where筛选条件
// 扩展方法形式 Where
List<Students> list2 = studentsList.Where(x=>x.Age<20).ToList();
// 表达式形式 Where
List<Students> val = (from s2 in list2 where s2.Id == 2 || s2.Id < 3 select s2).ToList();
三、let临时变量
/// let 创建变量
int[] ints = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
var query11 = from s in ints
let n = s % 2
where n == 0
select s;
四、Orderby排序
// 排序
var query7 = studentsList.OrderBy(s => s.Name); // OrderBy 升序
var query8 = studentsList.OrderByDescending(s => s.Id); // OrderByDescending 倒序
var query77 = from s in studentsList orderby s.Id ascending select s; // ascending升序
var query777 = from s in studentsList orderby s.Id descending select s; // descending倒序
五、分页查询Skip、Take、Top
- Skip:跳过前几条数据
- Take:获取指定数量元素
- Top:截取前几条数据
/* 表达式 */
List<string> nameList = (from u in list select u.name).Skip(3).Take(3).ToList();
/* 扩展方法 */
List<string> nameList = list.Skip(3).Take(3).Select(x => x.name).ToList();
六、分组查询 Group By
- 1、Group字句把select的对象根据一些标准进行分组。
- 2、从查询表达式返回的对象是从查询中枚举分组结果的可枚举类型。
- 3、每一个分组由一个叫做键的字段区分。
- 4、每一个分组本身是可枚举类型并可以枚举它的项。
/* 扩展方法 */
IEnumerable<IGrouping<string, User>> UserGroupByOccupation = list.GroupBy(s => s.occupation);
/* 表达式 */
IEnumerable<IGrouping<string, User>> UserGroupByOccupation
= from u in list
group u by u.occupation into n
结果:
/* 遍历 输出 */
foreach(IGrouping<string, User> u in UserGroupByOccupation)
{
Console.WriteLine(u.Key);
foreach (User user in u)
{
Console.WriteLine(PrintUserObject(user));
}
}
/* 输出结果 */
Teacher
{id = 1, name = Zhang Long, age = 38, gender = True, occupation = Teacher}
{id = 3, name = Zhang Shuai, age = 38, gender = False, occupation = Teacher}
Student
{id = 2, name = Zhang Jin, age = 18, gender = False, occupation = Student}
{id = 9, name = Hu Ziming, age = 21, gender = True, occupation = Student}
{id = 10, name = Hu Jin, age = 21, gender = False, occupation = Student}
Doctor
{id = 4, name = Liu Guangzhi, age = 38, gender = False, occupation = Doctor}
{id = 5, name = Liu Ziming, age = 38, gender = True, occupation = Doctor}
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor}
Builder
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder}
{id = 8, name = Jiang Long, age = 38, gender = True, occupation = Builder}
七、多表查询Join
SQL中常见的连接查询有:
- left join : 左连接,返回左表中所有的记录以及右表中连接字段相等的记录。
- right join : 右连接,返回右表中所有的记录以及左表中连接字段相等的记录。
- inner join : 内连接,又叫等值连接,只返回两个表中连接字段相等的行。
- full join : 外连接,返回两个表中的行:left join + right join。
- cross join : 结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数。
Linq只有Join这个函数。
- Linq中的Join连接查询是通过调换关联表和被关联表的顺序来转换左右连接的方向,通过调整Where和On等条件筛选函数的位置,来改变逻辑,实现更复杂的内连接全连接等功能。
// Join
// 表达式 (equals 同等)
var query3 = from s in studentsList
join c in classList on s.ClassId equals c.Id
select new {Id = s.Id,ClassId = s.ClassId,Name = s.Name,Age = s.Age,ClassName = c.ClassName };
// 扩展方法
var query4 = studentsList.Join(classList,s=>s.ClassId,c=>c.Id,(s,c)=>new { Id = s.Id, ClassId = s.ClassId, Name = s.Name, Age = s.Age, ClassName = c.ClassName });
八、聚合函数Count、Average、Max、Min、Sum
- 聚合函数是用于对查询结果进行汇总和计算的特殊函数。它们被用于计算一组行的总和、平均值、最大值、最小值等。在此文章中,将介绍SQL Server中一些常见的聚合函数及其用法。
(1).Count计数
/* 表达式 */
int count = (from u in list where u.occupation == "Teacher" where !u.gender where u.name.StartsWith("Zhang") select u).Count();
/* 扩展方法 */
int count = list.Count(u => u.occupation == "Teacher" && !u.gender && u.name.StartsWith("Zhang"));
(2).Average平均值
/* 表达式 */
double averageNum = (from u in list where u.occupation == "Doctor" where u.age<40 where u.name.StartsWith("Liu") select u.age).Average();
/* 扩展方法 */
double averageNum = list.Where(u => u.occupation == "Doctor" && u.age < 40 && u.name.StartsWith("Liu")).Select(u => u.age).Average();
(3).Max最大值、Min最小值、Sum和
这里仅需参考LINQ求平均值的例子,求最大/小值或者总和时,只需要把C#语句末尾的.Average()方法替换成.Max()/.Min()/.Sum()即可。
九、模糊查询
- 在C#中,使用LINQ进行模糊查询通常涉及到Where子句中对字符串的比较,可以使用string字符串中的方法来查找包含指定字符串的元素,或者使用正则表达式来实现更复杂的模糊查询。
// 查询名字中带有1的学生
var query9 = studentsList.Where(s => s.Name.Contains("1"));
十、子查询
var ordersWithProduct3 = orders.Where(o => o.OrderDetails.Any(d => d.ProductID == 3));
十一、投影
投影的过程就是把取得的结果进行处理,可以把结果集合内的对象只取其中一个或多个元素组成一个新的集合,生成一个原对象、基本类型、元组或匿名对象的新集合。
/* 表达式 */
List<User> userList = (from u in list where u.occupation == "Doctor" select u).ToList();
/* 扩展方法 */
List<User> userList = list.Where(p => p.occupation == "Doctor").ToList();
十二、集合的增删改查
增
/* 新增一个任意属性的用户到集合 */
/* C#版本1 */
list.Add(new User() {
id = 11,
name = "Liu Mingxiu",
age = 22,
gender = false,
occupation = "Doctor"
});
/* C#版本2(支持一次添加多个) */
IEnumerable<User> userAddList = new List<User>().Append(userAdd);
list.AddRange(userAddList);
删
/* 推荐使用RemoveAll方法批量删除 */
/* C#版本1 */
list.RemoveAll(item => item.occupation == "Doctor");
/* 也可以使用Remove方法单个删除 */
/* C#版本2 */
List<User> maps = list.Where(item => item.occupation == "Doctor").ToList();
foreach (User userDelete in maps){
list.Remove(userDelete);
}
/* C#版本3 */
List<User> maps = (from u in list where u.occupation == "Doctor" select u).ToList();
foreach (User userDelete in maps){
list.Remove(userDelete);
}
改
/* C#版本1 使用ForEach方法 */
salaryList.Where(item => item.occupation == "Doctor").ToList()
.ForEach(u => { u.salary = 10000; u.active = true; });
/* C#版本2 使用All方法(需要返回true) */
salaryList.Where(item => item.occupation == "Doctor").ToList()
.All( u => { u.salary = 10000; u.active = true; return true; });
查
LINQ查询参考 : C#进阶-LINQ表达式总结_c# linq-CSDN博客