C#进阶-LINQ表达式之多表查询Ⅰ

简介: 本篇文章我们将演示LINQ扩展包基础语法里的多表查询 ,包括交集、并集、差集、去重、合并等实际操作中常用的类型转换手法。目前LINQ支持两种语法,我会在每个案例前先用大家熟知的SQL语句表达,再在后面用C#的两种LINQ语法分别实现。LINQ语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。

多表查询

在学习之前,我们要做一些准备工作,我们需要创建User对象和包含User对象的集合,创建Salary对象和包含Salary对象的集合,作为后面查询和输出的数据源,参见这篇文章C#进阶之LINQ表达式总结完成准备工作。

数据源1:

数据源2:


1、交集 Intersect

如同数学中中的交集,集合[1,2,3]和集合[2,3,4]的交集是[2,3],Linq的交集是两种相同结果类型结果集的重合部分。

比如下面这个例子:

/* SQL里的表达: 求25岁以上且薪水超过17000的用户姓名、职业*/SELECTname,occupationFROMUserWHEREage>25; /*先查询25岁以上的用户姓名、职业*/INTERSECTSELECTname,occupationFROMSalaryWHEREsalary>17000; /*再查询薪水超过17000的用户姓名、职业*/
/* 在比较两个对象元素之前,我们先重写一个比较对象*/classCompareUser : IEqualityComparer<User>{
publicboolEquals(Userx, Usery)
  {
if (x.name==y.name&&x.occupation.ToLower() ==y.occupation.ToLower())
returntrue;
returnfalse;
  }
publicintGetHashCode(Userobj)
  {
return (obj.name+obj.occupation).Length;
  }
}
/*查询年龄大于25的用户集合,投影存储他们的姓名和职业*/List<User>user_list=list.Where(u=>u.age>25)
                .Select(g=>newUser(){
name=g.name,
occupation=g.occupation                }).ToList();
/*查询薪水大于17000的用户集合,投影存储他们的姓名和职业*/List<User>salary_list=salaryList.Where(u=>u.salary>17000)
                .Select(g=>newUser(){
name=g.name,
occupation=g.occupation                }).ToList();
/*取上面两个集合的交集为结果集*/List<User>result_list=user_list.Intersect(salary_list, newCompareUser()).ToList();
/* 遍历 输出 */foreach (Useruserinuser_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (Useruserinsalary_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (Useruserinresult_list)
{
Console.WriteLine(PrintUserObject(user));
}
/* 输出结果 *//* 年龄大于25的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher}
{id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher}
{id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}
{id=0, name=JiangLong, age=0, gender=False, occupation=Builder}
/* 薪水高于17000的用户集合 */{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}
/* 交集结果集 */{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}

2、并集 Union

如同数学中中的并集,集合[1,2,3]和集合[2,3,4]的交集是[1,2,3,4],Linq的并集是两种相同结果类型结果集的合并集合。

比如下面这个例子:

/* SQL里的表达: 求25岁以上和薪水少于8000的用户姓名、职业*/SELECTname,occupationFROMUserWHEREage>25; /*先查询25岁以上的用户姓名、职业*/UNIONSELECTname,occupationFROMSalaryWHEREsalary<8000; /*再查询薪水少于8000的用户姓名、职业*/
/*同样需要上面求交集时的比较对象*//*查询年龄大于25的用户集合,投影存储他们的姓名和职业*/List<User>user_list=list.Where(u=>u.age>25)
                .Select(g=>newUser(){
name=g.name,
occupation=g.occupation                }).ToList();
/*查询薪水少于8000的用户集合,投影存储他们的姓名和职业*/List<User>salary_list=salaryList.Where(u=>u.salary<8000)
                .Select(g=>newUser(){
name=g.name,
occupation=g.occupation                }).ToList();
/*取上面两个集合的交集为结果集*/List<User>result_list=user_list.Union(salary_list, newCompareUser()).ToList();
/* 遍历 输出 */foreach (Useruserinuser_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (Useruserinsalary_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (Useruserinresult_list)
{
Console.WriteLine(PrintUserObject(user));
}
/* 输出结果 *//* 年龄大于25的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher}
{id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher}
{id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}
{id=0, name=JiangLong, age=0, gender=False, occupation=Builder}
/* 薪水少于8000的用户集合 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher}
{id=0, name=ZhangJin, age=0, gender=False, occupation=Student}
{id=0, name=LiuJin, age=0, gender=False, occupation=Builder}
{id=0, name=HuZiming, age=0, gender=False, occupation=Student}
{id=0, name=HuJin, age=0, gender=False, occupation=Student}
/* 并集结果集 */{id=0, name=ZhangLong, age=0, gender=False, occupation=Teacher}
{id=0, name=ZhangShuai, age=0, gender=False, occupation=Teacher}
{id=0, name=LiuGuangzhi, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuZiming, age=0, gender=False, occupation=Doctor}
{id=0, name=LiuShuai, age=0, gender=False, occupation=Doctor}
{id=0, name=JiangLong, age=0, gender=False, occupation=Builder}
{id=0, name=ZhangJin, age=0, gender=False, occupation=Student}
{id=0, name=LiuJin, age=0, gender=False, occupation=Builder}
{id=0, name=HuZiming, age=0, gender=False, occupation=Student}
{id=0, name=HuJin, age=0, gender=False, occupation=Student}



3、全集 Concat

不同于并集(Union)去除了两个集合重复的元素,Concat保留重复的元素。

比如,{1,2,3}和{3,4,5}的Union结果是{1,2,3,4,5},而Concat的结果是{1,2,3,3,4,5}。


4、差集 Except

如同数学中中的差集,集合[1,2,3]和集合[2,3]的交集是[1],代码和交并集类似。

/*C#写法*/List<User>result_list=big_list.Except(small_list).ToList()

5、去重 Distinct

如同数学中中的去重,集合[1,2,3]和集合[2,3,4]的去重集是[1],即从集合[1,2,3]中剔除集合[2,3,4]中出现的集合[1,2,3]中的元素,[1,2,3]中剔除[2,3],故结果集是[1]。代码和交并集类似。

/*C#写法*/List<User>result_list=big_list.Distinct(small_list).ToList()


6、合并 Zip

Zip函数可以按照元素顺序合并两个集合的元素组成一个装纳新元素的集合,集合[1,2,3]和集合[2,3,4],可以合并成[12,23,34]这种字符串拼接的集合,也可以合并成[{1,2},{2,3},{3,4}]这种新的匿名对象集合。

/*C#写法*///合并为字符串拼接的新字符串集合IEnumerable<string>unionList=list.Zip(salaryList, (i1, i2) =>i1.name+", "+i2.occupation); 
//合并为新的匿名对象集合varunionList=list.Zip(salaryList, (i1, i2) =>new { n=i1.name, m=i2.occupation });
目录
相关文章
|
4月前
|
开发框架 自然语言处理 .NET
C#一分钟浅谈:LINQ 查询表达式的使用技巧
【9月更文挑战第6天】LINQ(Language Integrated Query)是C#开发中的强大工具,使查询数据集合变得简单且接近自然语言。本文从基础入手,通过具体示例讲解LINQ查询表达式的使用技巧,包括过滤、排序和分组等操作。同时,文章还探讨了常见问题及解决方法,如性能优化、过早枚举和类型转换等,帮助开发者写出更高效、易维护的代码。
107 15
|
4月前
|
C#
C#一分钟浅谈:Lambda 表达式和匿名方法
本文详细介绍了C#编程中的Lambda表达式与匿名方法,两者均可用于定义无名函数,使代码更简洁易维护。文章通过基础概念讲解和示例对比,展示了各自语法特点,如Lambda表达式的`(parameters) =&gt; expression`形式及匿名方法的`delegate(parameters)`结构。并通过实例演示了两者的应用差异,强调了在使用Lambda时应注意闭包问题及其解决策略,推荐优先使用Lambda表达式以增强代码可读性。
54 8
|
8月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---where和select用法(二)
C#学习相关系列之Linq用法---where和select用法(二)
489 2
|
6月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
8月前
|
C#
C#动态查询:巧用Expression组合多条件表达式
在C#中,利用`Expression`类和`AndAlso`、`OrElse`方法,可以组合两个`Expression&lt;Func&lt;T, bool&gt;&gt;`以实现动态多条件查询。该方法通过构建表达式树,方便地构建复杂查询。示例代码展示了如何创建表达式树,分别检查年龄大于等于18和姓名为&quot;John&quot;的条件,并使用`AndAlso`组合这两个条件,最终编译为可执行的委托进行测试。
324 1
|
7月前
|
开发框架 .NET 程序员
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
38 0
|
8月前
|
SQL 开发框架 .NET
C#linq表达式的应用
C#linq表达式的应用
44 0
|
8月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---group和join相关用法(三)
C#学习相关系列之Linq用法---group和join相关用法(三)
275 1
|
2月前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
42 3
|
13天前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
58 12