C#核心技术---Linq

目录

Linq介绍

Linq查询

语句查询

Linq扩展方法


Linq介绍

LINQ (读音link)------语言集成查询(Language Integrated Query),是.NET框架的扩展,一系列直接将查询功能集成到 C# 语言的技术统称,是一种使用类似SQL语句操作多种数据源的功能。

使用Linq,你可以从access数据库、程序对象的集合以及XML文档以及实现了IEnumerable或IEnumerable接口的集合类中查询数据。从.net framework3.5中开始引入,能够提升程序数据处理能力和开发效率,具有集成性、统一性、可扩展性、抽象性、说明式编程、可组成型、可转换性等优势。

Linq提供的程序

  • Linq to Object。提供程序查询内存中的集合和数组。
  • Linq to DataSet。提供程序查询ADO.NET数据集中的数据。
  • Linq to SQL。提供程序查询和修改Sql Server数据库中的数据,将应用程序中的对象模型映射到数据库表。
  • Linq to Entities。使用linq to entities时,会在后台将linq语句转换为sql语句与数据库交互,并能提供数据变化追踪。
  • Linq to XML。提供程序查询和修改XML,既能修改内存中的xml,也可以修改从文件中加载的。

Linq查询

Linq查询包括两种方式:

一、语句查询,

二、方法查询。

语句查询使用较多,也更容易理解,微软官网推荐使用。

语句查询

查询语法:

cs 复制代码
from 迭代变量  in 数据源  where ....   select 迭代变量
cs 复制代码
 //查询遍历数组
 //1.数据源
 int[] nums = { 12, 34, 9, 45, 52, 99, 76, 120 };
 //2.创建查询
 var numQuery = from m in nums
                select m;
 //3.执行查询
 foreach ( var m in numQuery)
 {
     Console.WriteLine(m);
 }

查询表达式在循环访问查询变量时(如上述示例中foreach),才会执行。

select子句,基于查询结果返回需要的值或字段,并能够对返回值指定类型。

cs 复制代码
  List<ItemInfo> itemInfos = GetItemList();//获取所有的名目列表
  //通过select返回列表中的所有名称属性值
  var items=from item in itemInfos select item.ItemName;
  foreach (var item in itemList01)
  {
     Console.WriteLine(item.Id+","+item.Name);
  }
  //通过select指定返回的类型
  var itemList01 = from item in list
                  select new
                  { //匿名类型
                      Id = item.ItemId,
                      Name = item.ItemName
                  };
 foreach (var item in itemList01)
 {
     Console.WriteLine(item.Id+","+item.Name);
 }
 

where子句:用来指定筛选的条件,与sql查询语句中的where功能一样。通过where子句获取到满足条件的结果.

cs 复制代码
var itemList01 = from item in list
                 where item.ItemId>102
                  select item.ItemName;
 foreach (var item in itemList02)
 {
     Console.WriteLine(item);
 }

orderby:用来排序,与sql中orderby的功能相同,使得返回结果可以根据某字段或某种规则实现升序或降序排列。

linq中语句默认展示为升序,降序使用【orderby 表达式 descending】

cs 复制代码
 var itemList3 = from item in list
                  where item.ItemId > 102
                  orderby item.ItemId descending
                  select item.ItemName;
 foreach (var item in itemList3)
 {
     Console.WriteLine(item);
 }

group by子句:用来对查询结果进行分组。且未指定key的情况下,key取值默认是true和false。如果分为多组,获取数据结果时需要手动遍历key获取对应的value

cs 复制代码
   List<IncomeInfo> incomeList = new List<IncomeInfo>()
  {
     new IncomeInfo(){IncomeId=1,IncomeName="收入1",ItemId=101},
     new IncomeInfo(){IncomeId=2,IncomeName="收入2",ItemId=101},
     new IncomeInfo(){IncomeId=3,IncomeName="收入3",ItemId=103},
     new IncomeInfo(){IncomeId=4,IncomeName="收入4",ItemId=102},
     new IncomeInfo(){IncomeId=5,IncomeName="收入5",ItemId=103},
     new IncomeInfo(){IncomeId=6,IncomeName="收入6",ItemId=104},
     new IncomeInfo(){IncomeId=7,IncomeName="收入7",ItemId=102},
     new IncomeInfo(){IncomeId=8,IncomeName="收入8",ItemId=105},
     new IncomeInfo(){IncomeId=9,IncomeName="收入9",ItemId=104},
     new IncomeInfo(){IncomeId=10,IncomeName="收入10",ItemId=106}
  };
  //把收入记录信息按ItemId分组
  var incomeList1 = from income in incomeList group income by income.ItemId;
  //分组打印
  foreach(var income in incomeList1)
  {
      Console.WriteLine(income.Key);
      foreach(var item in income)
      {
          Console.WriteLine(item.ItemId +"--"+item.IncomeName);
      }
      Console.WriteLine();
  }
//输出结果:
101
101--收入1
101--收入2

103
103--收入3
103--收入5

102
102--收入4
102--收入7

104
104--收入6
104--收入9

105
105--收入8

106
106--收入10

Join子句:用于联合查询,一般会存在两个数据源,且两个数据源中有相同的字段可进行比较。使用格式为【join 数据 in 数据源1 on key1 equals key2】

cs 复制代码
//inner join 只匹配能匹配上的
var incomeList2 = from item in list
                   join income in incomeList on item.ItemId equals income.ItemId
                   select new
                   {
                       ItemId = item.ItemId,
                       ItemName = item.ItemName,
                       IncomeId = income.IncomeId,
                       Income = income.IncomeName
                   };
foreach (var item in incomeList2)
{
    Console.WriteLine($"名目编号:{item.ItemId}, 名目:{item.ItemName},  收入编号:{item.IncomeId},  收入名称:{item.Income}");
}

//left join 能左边为准,右边匹配不上的,就是null
var incomeList3= from income in incomeList
                   join item in list on income.ItemId equals item.ItemId
                   into ItemsNew
                   from newItem in ItemsNew.DefaultIfEmpty() //如果序列为空就为默认值
                   select new
                   {
                       IncomeId = income.IncomeId,
                       Income = income.IncomeName,
                       ItemName = newItem == null ? "无名目" : newItem.ItemName
                   };
foreach (var item in incomeList3)
{
    Console.WriteLine($" 收入编号:{item.IncomeId},  收入名称:{item.Income}, 名目:{item.ItemName}");
}
 //输出:
 收入编号:1,  收入名称:收入1, 名目:银行转账
 收入编号:2,  收入名称:收入2, 名目:银行转账
 收入编号:3,  收入名称:收入3, 名目:无名目
 收入编号:4,  收入名称:收入4, 名目:股票收入
 收入编号:5,  收入名称:收入5, 名目:无名目
 收入编号:6,  收入名称:收入6, 名目:工资发放
 收入编号:7,  收入名称:收入7, 名目:股票收入
 收入编号:8,  收入名称:收入8, 名目:朋友还钱
 收入编号:9,  收入名称:收入9, 名目:工资发放
 收入编号:10,  收入名称:收入10, 名目:无名目
 
 //right join 以右边为准,左边匹配不上的,就是null
 var incomeList4 = from item in list
                    join income in incomeList on item.ItemId equals income.ItemId
                    into incomesNew  //符合条件的收入列表
                    from newIncome in incomesNew.DefaultIfEmpty() //如果序列为空就为默认值
                    select new
                    {
                        IncomeId = newIncome == null ? 0 : newIncome.IncomeId,
                        Income = newIncome == null ? "无":newIncome.IncomeName,
                        ItemName = item.ItemName
                    };
 foreach (var item in incomeList4)
 {
     Console.WriteLine($"名目:{item.ItemName} , 收入编号:{item.IncomeId},  收入名称:{item.Income}");
 }
收入编号:1,  收入名称:收入1,名目:银行转账
收入编号:2,  收入名称:收入2,名目:银行转账
收入编号:4,  收入名称:收入4,名目:股票收入
收入编号:7,  收入名称:收入7,名目:股票收入
收入编号:0,  收入名称:无,   名目:客户付款
收入编号:6,  收入名称:收入6,名目:工资发放
收入编号:9,  收入名称:收入9,名目:工资发放
收入编号:8,  收入名称:收入8,名目:朋友还钱

Linq扩展方法

Linq查询中,为了更加清晰明了的阅读,我们一般采用查询语法,但有些查询操作没有等效的查询表达式,只能采用方法查询,即调用内部方法,有些场景中也可以将查询语法和方法语法结合使用。

cs 复制代码
int[] nums = { 12, 34, 9, 45, 52, 99, 76, 120 };
var queryList=from num in nums select num;
var avg=queryList.Average();//求平均
var max=queryList.Max();//求最大值
var min=queryList.Min();//求最小值
var newList=queryList.OrderBy(n=>n);
 
var numList1=nums.Where(num=>num>40);
 var itemList4 = list.Where(item => item.ItemId > 103);
 //链式写法 Where().OrderBy().Select()....
 var itemList5 = list.Where(item => item.ItemId > 102).OrderByDescending(item=>item.ItemId).Select(item =>      new
   {
     Id = item.ItemId,
     Name = item.ItemName
    });
    
 //Distinct/First/Find
 var nums2=  nums1.Distinct();//去重
 ItemInfo item1=list.OrderBy(item=>item.ItemId).First();//返回第一个元素 若集合为空,会异常
 ItemInfo item2 = list.OrderBy(item => item.ItemId).FirstOrDefault();//返回第一个元素 若集合为空,返回默认值
 int maxId=list.Max(item=>item.ItemId);
 int minId=list.Min(item=>item.ItemId);
 int count = nums1.Distinct().Count();//获取集合总元素数
 
  var itemList6 = list.Where(item => item.ItemId > 101);
  var itemList7 = itemList6.Union(itemList4);//合并成一个集合,去重
  var itemList8 = itemList6.Concat(itemList4);//合并成一个集合,不去重

  var itemList9 = itemList6.Except(itemList4);//得到一个差集,去掉公共的部分
  //Skip/Take  跳过指定数目的元素/连续取指定数目的元素
  var itemList10 = list.Skip(2).Take(3);
  
  //Join 连接两个集合,关联属性,合并一个集合,包含两个集合中的信息  inner join
  var incomeList7 = list.Join(incomeList, item => item.ItemId, income => income.ItemId, (item, income) => new
  {
      ItemId = item.ItemId,
      ItemName = item.ItemName,
      Id = income.ItemId,
      Income = income.IncomeName
  });
  foreach (var item in incomeList7)
  {
      Console.WriteLine($"名目编号:{item.ItemId}, 名目:{item.ItemName},  收入编号:{item.Id},  收入名称:{item.Income}");
  }
  //分组 
  var incomeList8 = incomeList.GroupBy(income => income.ItemId);
  foreach(var item in incomeList8)
  {
      Console.WriteLine(item.Key);
      foreach(var it in item)
      {
          Console.WriteLine(it.IncomeId + "," + it.IncomeName);
      }
  }

  //GroupJoin ---等同性将两个序列的元素进行关联,并对结果进行分组。
  var groups = list.GroupJoin(incomeList, item => item.ItemId, income => income.ItemId, (item, income) => new
  {
      ItemId = item.ItemId,
      ItemName = item.ItemName,
      Records = income.Select(r => new { Id = r.IncomeId, Income = r.IncomeName })
  }) ;

  foreach(var item in groups)
  {
      Console.WriteLine(item.ItemId+","+item.ItemName);
      foreach(var r in item.Records)
      {
          Console.WriteLine("编号:"+r.Id+" , 名称:"+r.Income);
      }
  }
相关推荐
软件黑马王子1 小时前
C#初级教程(4)——流程控制:从基础到实践
开发语言·c#
闲猫1 小时前
go orm GORM
开发语言·后端·golang
李白同学3 小时前
【C语言】结构体内存对齐问题
c语言·开发语言
黑子哥呢?4 小时前
安装Bash completion解决tab不能补全问题
开发语言·bash
青龙小码农4 小时前
yum报错:bash: /usr/bin/yum: /usr/bin/python: 坏的解释器:没有那个文件或目录
开发语言·python·bash·liunx
大数据追光猿4 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
彳卸风5 小时前
Unable to parse timestamp value: “20250220135445“, expected format is
开发语言
dorabighead5 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
风与沙的较量丶6 小时前
Java中的局部变量和成员变量在内存中的位置
java·开发语言
水煮庄周鱼鱼6 小时前
C# 入门简介
开发语言·c#