目录
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查询包括两种方式:
一、语句查询,
二、方法查询。
语句查询使用较多,也更容易理解,微软官网推荐使用。
语句查询
查询语法:
from 迭代变量 in 数据源 where .... select 迭代变量
//查询遍历数组//1.数据源int[] nums = { 12, 34, 9, 45, 52, 99, 76, 120 };//2.创建查询var numQuery = from m in numsselect m;//3.执行查询foreach ( var m in numQuery){Console.WriteLine(m);}
查询表达式在循环访问查询变量时(如上述示例中foreach),才会执行。
select子句,基于查询结果返回需要的值或字段,并能够对返回值指定类型。
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 listselect new{ //匿名类型Id = item.ItemId,Name = item.ItemName};foreach (var item in itemList01){Console.WriteLine(item.Id+","+item.Name);}
where子句:用来指定筛选的条件,与sql查询语句中的where功能一样。通过where子句获取到满足条件的结果.
var itemList01 = from item in listwhere item.ItemId>102select item.ItemName;foreach (var item in itemList02){Console.WriteLine(item);}
orderby:用来排序,与sql中orderby的功能相同,使得返回结果可以根据某字段或某种规则实现升序或降序排列。
linq中语句默认展示为升序,降序使用【orderby 表达式 descending】
var itemList3 = from item in listwhere item.ItemId > 102orderby item.ItemId descendingselect item.ItemName;foreach (var item in itemList3){Console.WriteLine(item);}
group by子句:用来对查询结果进行分组。且未指定key的情况下,key取值默认是true和false。如果分为多组,获取数据结果时需要手动遍历key获取对应的value
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--收入2103
103--收入3
103--收入5102
102--收入4
102--收入7104
104--收入6
104--收入9105
105--收入8106
106--收入10
Join子句:用于联合查询,一般会存在两个数据源,且两个数据源中有相同的字段可进行比较。使用格式为【join 数据 in 数据源1 on key1 equals key2】
//inner join 只匹配能匹配上的
var incomeList2 = from item in listjoin income in incomeList on item.ItemId equals income.ItemIdselect 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 incomeListjoin item in list on income.ItemId equals item.ItemIdinto ItemsNewfrom 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 以右边为准,左边匹配不上的,就是nullvar incomeList4 = from item in listjoin income in incomeList on item.ItemId equals income.ItemIdinto 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查询中,为了更加清晰明了的阅读,我们一般采用查询语法,但有些查询操作没有等效的查询表达式,只能采用方法查询,即调用内部方法,有些场景中也可以将查询语法和方法语法结合使用。
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/Findvar 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 joinvar 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);}}