C#使用LINQ进行简单的查询

LINQ的简单查询

查询

假设有一个自定义类Kongfu:

class Kongfu

{

    public int KongfuId;

    public string KongfuName;

    public int Power;

 

    public Kongfu() { }

}

Main中实例了一个Kongfu类列表:

var kongfu = new List<Kongfu>

{

    new Kongfu {KongfuId = 1, KongfuName = "打狗棒法", Power = 90},

new Kongfu {KongfuId = 2, KongfuName = "降龙十八掌", Power = 95},

new Kongfu {KongfuId = 3, KongfuName = "葵花宝典", Power = 100}

 };

如果我们要过滤列表中Power>90的元素,一般情况下使用forforeach过于麻烦,此时我们可以使用LINQ做查询和返回

Main:

var res = from k in kongfu

where k.Power>90 //判断

select k; //返回k至res中,此时k是Kongfu类,所以res也是一个Kongfu的列表

foreach(var temp in res)

{

Console.WriteLine(temp); //需要重写Kongfu类的ToString()方法

}

Console.ReadKey();

当有多个条件需要判断时可用&&隔开,比如

where k.Power>90 && k.KongfuName == ”降龙十八掌”

 

查询的关键字

以下部分来自博客:https://blog.csdn.net/IT_choshim/article/details/83658748

From:子句被查询的数据源(相当于for循环)多个from表示从多个数据源查询数据(c#会把符合from字句的查询表达式转换为SelectMany()扩展方法)

Where:子句指定元素所满足的过滤条件(相当于if判断)多个Where字句则表示了并列条件,必须全部满足才能入选,每个字句可以使用&& ||连接多个表达式

orderbydescending:表现方式(相当于排序方式,升序、降序。。。)

Select指定查询要返回的目标数据(相当于return)可以指定任何类型,甚至是匿名类型

使用select创建新数组(select new{成员1,成员2,.....};)时一般我们会加上成员名如:

select new{_count=k.Count(),_name=k.Name};//输出 _count=.......,_name=.......

但也可以不加成员名,此时有两种情况。

第一种:

select new{k.Count(),k,Name};//k.Count()编译不通过,即方法不能作为变量名直接使用

第二种:

select new{k.Age,k,Name};//输出 Age=.....,Name=...... 则会输出原本的变量名

into:提供一个临时的标识符,可以引用join、group和select字句的结果。

(1)直接出现在join字句之后的into关键字会被翻译为Groupjoin(into之前的变量可以继续使用)

2)select或group字句之后的into会重新开始一个查询,让我们可以继续引入Where,orderby和select字句,它是对分布构建查询表达式的一种简写方式(into之前的查询变量都不可以再使用)

var intoLinq = from num in peoList
                           group num by num.city into groupnum

以上示例:into 字面解释意为“打入”,以上事例将遍历proList得到的num筛选出city属性放入groupnum中,这里的groupnam可以看作是一个集合,这个集合存的是city属性

let:引入用于存储查询表达式结果的范围变量,通常能达到层次感会更好,使代码更易于阅读

string[] strings = { "hello world.", "lin qing xia", "wang zu xian" };

            var strs = from s in strings

                       let words = s.Split( )

                       from word in words

                       let w = word.ToUpper()

                       select w;

            foreach(var s in strs)

            {

                Console.WriteLine(s);

            }

将遍历的元素进行处理,并将处理结果存放到words,这里的words也可看作一个集合

 

联合查询

联合查询可以同时查询多个对象。而且查询时每个对象会将元素一一匹配。比如列表对象1中有4个元素,列表对象2中有5个元素,则会匹配4*5=20次,所以在添加到结果时要慎重,过滤逻辑要写清楚,否则容易重复添加。

以上面的Kongfu和新自定义类MartialArtsMaster类为例:

class MartialArtsMaster

{

     public int Id { get; set; }

     public string Name { get; set; }

     public int Age { get; set; }

     public string Menpai { get; set; }

     public string Kungfu { get; set; }

     public int Level { get; set; }

}

假设我们实例好了一个MartialArtsMaster数组,命名为masterList

//Linq联合查询

var res = from k in kongfu

from m in masterList

where k.KongfuName == m.Kungfu && k.Power>90
select m;//

 

然后用foreach遍历res输出即可

如若我们要同时返回满足条件的两个数组中的元素,则可以创建一个新的临时对象,将①改为:

 

select new { _master = m , _kungfu=k };//

这样res中就能同时插入Kongfu类和MartialArtsMaster类中满足条件的元素了

 

 

扩展方法写法

 

查询

 

扩展方法都是调用List中的方法,不同于以上LINQ表达式的查询,我们还有一种方法可以过滤元素:

 

同样是Kongfu类和kongfu列表:

 

var res = kongfu.Where(Method1); //使用Where(),参数需要传入一个方法,返回值为bool,如果为true,将元素添加到到res中;否则过滤掉


foreach(var temp in res)


{


Console.WriteLine(temp); //需要重写Kongfu类的ToString()方法


}


//过滤方法
static bool Method1(Kongfu kongfu)


{


if(kongfu.Power>90) return true;


return false;


}

 

 

注意Where()是传入一个方法。

 

再简便点可以直接不写方法,引入Lambda表达式①改为:

 

var res = kongfu.Where(k=>k.Power>90);

 

这样的话②都不用写。

 

当有多个参数时③可写成:

 

var res = kongfu.Where(k=>k.Power>90 && k.KongfuName==”降龙十八掌”);

 

 

联合查询

 

LINQ中的联合查询可以写成这种形式:

 

//扩展方法的联合查询


var res = masterList.SelectMany(m => kongfu, (m, k) => new {_master = m, _konfu = k})


    .Where(x => x._master.Kungfu == x._konfu.KongfuName && x._konfu.Power > 90);

 

 C#使用LINQ进行简单的查询

 

官方释义:将序列的每个元素投影到 IEnumerable<TCollection>,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数。

 

这个用法,可以对已合成一个大集合的每个元素调用结果选择器,返回自己想要的集合类型。

 

第一个参数:m=>kongfu

m指定是想要处理的每个masterList对象,而kongfu则是想让m实例映射的kongfu集合;

 

第二个参数:(m, k) => new { _master= m, _kongfu = k }

mk分别指定是映射后(其实有点类似数据库的CROSS JOIN)的MartialArtsMaster实例与Kungfu实例,如名为M1MartialArtsMaster类,其kongfu名为k1,那么mk就是:M1/k1(指定是名称),处理其他MartialArtsMaster类也是如此。而new { _master= m, _kongfu = k }则是返回的一个由自己定义的匿名类型。

 

 

实际上SelectMany对应的LINQ语句为:

 

var res = from m in masterList


from k in kongfu


select new{ masterList.kungfu == kongfu && kongfu.Power > 90 };

 

SelectMany()用来指定集合,Where用来查询并返回所需元素的,两者结合即可起到运算或筛选的效果。

 

 

 

里面包含了大量的委托Lambda表达式的使用,一开始不懂可以理解,之后遇到再深入学习

 

SelectMany()具体可以查看博客:https://www.cnblogs.com/cncc/p/9840463.html,内有详细解析

 

 

对结果进行排序

 

使用OrderBy()进行排序

 

依然是武林高手MartialArtsMaster类的例子:

 

var res = mastersList.Where(m=>m.Menpai=="华山").OrderBy(m=>m.Age);//根据年龄,默认从小到大

 

如果需要从大到小的排序,则使用OrderByDescending();

 

若需要排序后再排序,则在OrderBy()或OrderByDescending()后面加上ThenBy()ThenByDescending();

 

 

集合联合

 

集合联合使用join … in … on … equals … 的形式,实现集合的多条件连接,有点类似于SelectMany()

 

依然以masterList和kongfu对象为例:

 

var res = from m in masterList


join k in kongfu on m.Kungfu equals k.KongfuName


//将kongfu联合masterList,筛选出其中功夫名相同的对象


Where k.Power>90


select new{_master=m,_kongfu =k };

 

 

分组查询

 

使用 into进行分组

 

以武林高手和武功对象为例,输出所有武功的信息和修炼武功的高手的数量:

 

var res = from k in kongfu

join m in MasterList on k.KongfuName equals m.Kungfu

into groups

OrderBy groups.Count()//按照数量排序

select new {_kungfu=k,_count=groups.Count()};

 

 

 

按照自身字段分组 group

 

使用group by对自身分组

 

比如,我们要将master中的成员按照武学分组,并输出修炼该武学的人数和武学名

 

var res = from m in masterList


group g by m.kongfu


into g


select new{g.Count(),g.Key};//输出人数,武学名

 

关于g.KeyKey表示分组根据的属性

 

 

 

量词操作符 any all 判断集合中是否符合某个条件

 

使用List<T>.All(判断条件)可以判断集合内的所有元素是否符合条件,返回值为bool

 

使用List<T>.Any(判断条件)可以判断集合内的元素是否有一个符合条件,返回值为bool

 

例如:

 

bool res1 = masterList.Any(m => m.Menpai == "丐帮");//判断组内是否有一个元素满足条件


Console.WriteLine(res1);//true


res1 = masterList.All(m => m.Menpai == "丐帮");//判断组内是否全部元素都满足条件


Console.WriteLine(res1);//false

 

C#使用LINQ进行简单的查询

上一篇:MonogDB -索引(一)概述


下一篇:Oracle学习笔记 3 --条件查询( where )