本篇文章我们将演示LINQ扩展包的基础语法,以Select查询、Count计数、Average平均值、OrderBy排序函数为例,目前LINQ支持两种语法,我会在每个案例前先用大家熟知的SQL语句表达,再在后面用C#的两种LINQ语法分别实现。LINQ语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。
在学习之前,我们要做一些准备工作,我们需要创建User对象和包含User对象的集合,作为后面查询和输出的数据源。
C#类:
class User
{
public int id { get; set; }
public string name { get; set; }
public bool gender { get; set; }//male: true; female: fasle
public int age { get; set; }
public string occupation { get; set; } //职业
}
List<User> list = new List<User>()
{
new User { id = 1, name = "Zhang Long", age = 38, gender = true, occupation = "Teacher"},
new User { id = 2, name = "Zhang Jin", age = 18, gender = false, occupation = "Student"},
new User { id = 3, name = "Zhang Shuai", age = 38, gender = false, occupation = "Teacher"},
new User { id = 4, name = "Liu Guangzhi", age = 38, gender = false, occupation = "Doctor"},
new User { id = 5, name = "Liu Ziming", age = 38, gender = true, occupation = "Doctor"},
new User { id = 6, name = "Liu Shuai", age = 29, gender = false, occupation = "Doctor"},
new User { id = 7, name = "Liu Jin", age = 21, gender = true, occupation = "Builder"},
new User { id = 8, name = "Jiang Long", age = 38, gender = true, occupation = "Builder"},
new User { id = 9, name = "Hu Ziming", age = 21, gender = true, occupation = "Student"},
new User { id = 10, name = "Hu Jin", age = 21, gender = false, occupation = "Student"}
};
SQL数据源:
/* SQL里的表达: 查找用户里职业是医生的人的姓名,按照年龄倒序输出 */
select name from user where occupation = "Doctor" order by age desc;
/* C#版本1 */
List<string> nameList = (from u in list where u.occupation == "Doctor" orderby u.age descending select u.name).ToList();
/* C#版本2 */
List<string> nameList = list.OrderByDescending(u => u.age).Where(p => p.occupation == "Doctor").Select(x => x.name).ToList();
Liu Guangzhi, Liu Ziming, Liu Shuai /* 输出结果 */
其中,C#版本1的语法是 from 变量名 in 集合 where 条件 orderby 条件 select 结果变量,得到的结果是LINQ的内置类型<Enumerable>,可直接视为匿名类型(var),需用.ToList()转换为List<string>类型。C#版本2是LINQ的一种扩展写法,是更加常用的写法。
/* SQL里的表达: 查找用户里姓Zhang的女性教师的数量*/
select count(*) from user where occupation = "Teacher" and name like 'Zhang%' and gender = false;
/* C#版本1 */
int count = (from u in list where u.occupation == "Teacher" where !u.gender where u.name.StartsWith("Zhang") select u).Count();
/* C#版本2 */
int count = list.Count(u => u.occupation == "Teacher" && !u.gender && u.name.StartsWith("Zhang"));
1 /* 输出结果 */
/* SQL里的表达: 查找用户里的小于40岁的某姓医生的平均年龄 */
select avg(age) from user where occupation = "Doctor" and name like 'Liu%' and age < 40;
/* C#版本1 */
double averageNum = (from u in list where u.occupation == "Doctor" where u.age<40 where u.name.StartsWith("Liu") select u.age).Average();
/* C#版本2 */
double averageNum = list.Where(u => u.occupation == "Doctor" && u.age < 40 && u.name.StartsWith("Liu")).Select(u => u.age).Average();
35 /* 输出结果 */
这里仅需参考LINQ求平均值的例子,求最大/小值或者总和时,只需要把C#语句末尾的.Average()方法替换成.Max()/.Min()/.Sum()即可。
/* SQL里的表达: 查找用户里名字带Jin的人,优先按照年龄倒序,其次按照姓氏拼音正序,输出这些人的全部信息 */
select * from user where name like '%Jin%' order by age desc name asc;
/* C#版本1 */
List<User> userList = (from u in list where u.name.Contains("Jin") orderby u.age descending orderby u.name select u).ToList();
/* C#版本2 */
List<User> userList = list.Where(u => u.name.Contains("Jin")).OrderByDescending(u => u.age).OrderBy(u => u.name).ToList();
{id = 10, name = Hu Jin, age = 21, gender = False, occupation = Student},
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder},
{id = 2, name = Zhang Jin, age = 18, gender = False, occupation = Student} /* 输出结
Any()函数判断判断是否至少存在一个符合元素符合条件;All()函数判断是否全部元素都符合条件;下面以Any()函数为例:
/* SQL里的表达: 查找用户里是否存在年龄小于30岁职业是医生的女性 */
select count(*) from user where occupation = "Doctor" and gender = false and age < 30; //返回符合的个数
/* C#版本1 */
bool result = (from u in list where u.age < 30 where !u.gender where u.occupation == "Doctor" select u).Any();
/* C#版本2 */
bool result = list.Any(u => u.age < 30 && !u.gender && u.occupation == "Doctor");
数据源中所有医生如下:
可以看到,目前我们数据源里是有Liu Shuai这一条符合三个属性(小于30岁/医生/女性)的。
true /* 输出结果 */
这里Any()函数是只要存在至少一个符合全部条件的结果,即返回布尔值True,只有在一个都不符合条件的情况下才会返回False;与之相反,All()函数只有在全部数据都符合全部条件的情况下,才会返回True,只要有一条不满足就返回False;All()函数的语法和Any()函数的语法相同,上面的例子把Any()直接替换成All()即可。
Single()判断是否只有一个元素符合条件,若成立则返回该元素,若不成立则抛出异常。
/* SQL里的表达: 查找用户里年龄小于30岁职业是医生的女性 */
select * from user where occupation = "Doctor" and gender = false and age < 30
/* C#版本1 */
User userResult = (from u in list where u.age < 30 where !u.gender where u.occupation == "Doctor" select u).Single();
/* C#版本2 */
User userResult = list.Single(u => u.age < 30 && !u.gender && u.occupation == "Doctor");
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor} /* 输出结果 */
Single()要求有且只有一条满足要求的数据,多条满足条件或一条也没有,此方法会报错; SingleOrDefault()要求最多有一条满足要求的数据,多条满足条件,此方法会报错;没有数据则返回数据类型的默认值; 类似的还有First()、FirstOrDefault()、Last()、LastOrDefault(),这里给大家做了一个异常表格记录了各种情况的返回值:
函数 | 没有满足 | 一条满足 | 多条满足 | list本身为Null |
---|---|---|---|---|
Single | 异常 | 该元素 | 异常 | 异常 |
SingleOrDefault | 默认值 | 该元素 | 异常 | 异常 |
First | 异常 | 该元素 | 第一个元素 | 异常 |
FirstOrDefault | 默认值 | 该元素 | 第一个元素 | 异常 |
Last | 异常 | 该元素 | 末尾的元素 | 异常 |
LastOrDefault | 默认值 | 该元素 | 末尾的元素 | 异常 |
面对可能出现的异常,我们一般在使用这类方法时要进行Try{…}Catch(…){…}。
/* SQL里的表达: 查找用户表自然排序第4个人到第6个人的姓名*/
select name from user limit 3,3;
/* C#版本1 */
List<string> nameList = (from u in list select u.name).Skip(3).Take(3).ToList();
/* C#版本2 */
List<string> nameList = list.Skip(3).Take(3).Select(x => x.name).ToList();
Liu Guangzhi, Liu Ziming, Liu Shuai /* 输出结果 */
同理,Top(n)表示截取前n条数据。
在现代编程中,Linq(Language Integrated Query)表达式是.NET语言中的一项强大功能,允许开发者以声明式方式查询和操作数据。Linq可以用于各种数据源,包括数组、列表、XML文件以及数据库。本部分将总结Linq的关键特性,并通过一个同类程序集的对比表格,展示Linq在不同环境下的应用与效能。
程序集 | 数据源支持 | 性能表现 | 易用性评分 | 特点 |
---|---|---|---|---|
Linq to SQL | SQL数据库 | 高 | 5/5 | 直接与SQL Server交互 |
Linq to XML | XML文件 | 中 | 4/5 | 简化XML数据处理 |
Linq to Entities | 关系型和非关系型数据库 | 高 | 5/5 | 支持复杂的数据查询和操作 |
Linq to Objects | 内存中的对象集合 | 低 | 5/5 | 适用于小型集合的快速查询 |
Linq技术为.NET开发者提供了一个强大的工具,能够简化复杂数据操作并整合不同的数据源。其语法的统一性和强类型特征使得开发过程中数据操作更加安全,同时也更加直观。尽管在处理非常大的数据集时性能可能会成问题,但对于大多数日常开发任务而言,Linq提供了既高效又易用的解决方案。通过使用Linq,开发者可以减少代码量,提高代码质量,并能更好地维护和扩展其应用程序。无论是在企业级应用还是在小型项目中,Linq都证明了自己的价值,是.NET生态中不可或缺的一部分。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。