LINQ标准查询操作符学习笔记二

三、使用Linq进行查询

有了这些预备知识和实体类,我们就可以使用Linq进行查询了。

       1、简单的筛选

使用Where子句可以对数据源进行简单的筛选。下变例子是找出至少赢得15场比赛的奥地利车手:

        /// <summary>
        /// 1、最简单的查询
        /// </summary>
        static void LinqQuery1()
        {
            var query = from r in Formula1.GetChampions()
                        where (r.Country == "Brazil" || r.Country == "Austria") && r.Wins > 15
                        orderby r.Wins descending
                        select r;
            foreach (var racer in query)
            {
                Console.WriteLine("{0:A}", racer);
            }
        }

这段代码的功能可以使用System.Linq中的扩展方法来实现:

【代码】

          var query2 = Formula1.GetChampions()
                .Where(r => r.Country == "Brazil" || r.Country == "Austria")
                .Select(r=>r);

注:并不是所有的查询都可以使用Linq查询或者扩展方法都可以实现的。高级查询需要使用扩展方法。

2、用索引进行筛选

Where()扩展方法的一个重载中,可以对该方法传递第二个参数:索引。索引是筛选器返回的每个结果的计数器,可以在表达式中使用索引,执行一些索引相关的计算。现编的代码使用Where()扩展方法,返回姓氏以A开头,索引为偶数的车手:

/// <summary>
/// 2、使用索引i进行选 
/// </summary>
        static void LinqQuery2()
        {

            //使用索引i进行筛选
             var query = Formula1.GetChampions()
                 .Where((r, i) => r.LastName.StartsWith("A") && i % 2 != 0);
            foreach (var item in query)
            {
                Console.WriteLine("{0:A}", item);
            }
        }
 

 

       3、筛选出不同的数据类型

使用OfType()扩展方法,可以实现基于类型的筛选。下面的代码中定义了包含了string和int类型的对象,使用OfType()方法从集合中找出字符串:

        /// <summary>
        /// 3、类型筛选         
        /// </summary>
        static void LinqQuery3()
        {
            object[] data = { "one", 1, 2, 3, "two", "three" };
            var query = data.OfType<string>();

            foreach (var item in query)
            {
                Console.WriteLine(item);
            }
        }

       4、复合的from子句

复合的from子句用于对这样一种情况的查询:需要根据对象的一个成员进行筛选,而这个成员本身是一组数据。

本例中,Racer类定义的属性Cars就是这样的一个属性。Cars是一个字符串数组。

使用如下的Linq查询可以筛选出嘉实法拉利的所有冠军:

            var query = from r in Formula1.GetChampions()
                        from c in r.Cars
                        where c == "Ferrari"
                        orderby r.LastName
                        select r;

 其中,第一个from子句用于访问从Formyla1.GetChampions方法返回的Racer对象,第二个from子句访问Racer类的Cars属性,返回所有string类型的赛车,最后使用Where子句从这些赛车中筛选出所有冠军。

这里C#编译器将符合的from子句和Linq查询转换成SelectMany()方法,SelectMany()方法可以用于迭代序列的序列。使用SelectMany()扩展方法的代码如下:

            var query = Formula1.GetChampions()
                .SelectMany(r => r.Cars, (r, c) => new { Racer = r, Car = c })
                .Where(r => r.Car == "Ferrari")
                .OrderBy(r => r.Racer.FirstName)
                .Select(r => r.Racer.FirstName + " " + r.Racer.LastName);

这里SelectMany()方法的第一个参数是隐式参数,他从GetChampions方法中接收Racer对象序列,第二个参数是collectionSelector委托,其中定义了内部序列。在Lambda表达式r=>r.Cars中,返回赛车集合。第三个参数是一个Func<T>委托,这里为每个Car调用该委托接收Racer和Cars对象。Lambda表达式创建了一个包含了Racer和Cars属性的匿名的类型。这个SelectMany方法的结果摊平了赛手和赛车的层次结构,为每个赛车返回匿名类型的一个新对象耦合。

这段解释有点拗口,因为Lambda表达式确实比较难以解释,还有使用了几个Func<T>委托,不了解委托看这段代码简直就是天书。不过VS的职能提示挺管用的,在敲出几个代码之后看看他的提示在继续写也是不错的。

       5、对筛选结果进行排序

使用orderby和orderby descending子句或者OrderBy()和OrderByDescending()扩展方法可以实现对筛选结果的排序。

下面这段代码是对筛选出来的赛手使用赢得比赛的次数进行排序:

            //简单的Linq语句查询排序
            var query1 = from r in Formula1.GetChampions()
                        where r.Country == "Brazil"
                        orderby r.Wins descending
                        select r;

转换成扩展方法后的实现:

            //使用扩展方法
            var query2 = Formula1.GetChampions()
                .Where(r => r.Country == "Brazil")
                .OrderByDescending(r => r.Wins)
                .ThenByDescending(r=>r.LastName)
                .Select(r => r);

最后还可以使用Take方法对结果进一步筛选:

            //使用Take子句提取前十项数据
            var query3 = (from r in Formula1.GetChampions()
                         orderby r.Country, r.LastName, r.FirstName
                         select r)
                             .Take(10);

            //使用扩展方法查询
            var query = Formula1.GetChampions()
                .OrderBy(r => r.Country)
                .ThenBy(r => r.LastName)
                .ThenBy(r => r.FirstName)
                .Take(10)
                .Select(r => r);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值