C#--Linq使用小记

           LINQ(Language Integrated Query )语言集成查询,可为以下对象编写 LINQ 查询:SQL Server 数据库、XML 文档、ADO.NET 数据集以及支持 IEnumerable 或泛型 IEnumerable<T> 接口的任何对象集合。 此外,第三方也为许多 Web 服务和其他数据库实现提供了 LINQ 支持。

示例:

using System.Collections.Generic;
using System.Linq;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;

namespace CsharpSenior
{
    class LinqHelper
    {
        public List<Student> Students { get; set; }
        public List<Course> Courses { get; set; }

        public LinqHelper()
        {
            GetDataSource();
        }
  
        public void Query()
        {
            /*一个普通查询
             * 结构:from + 迭代变量名称 + in +数据源(必须是可枚举类型)
             * +where(条件过滤)
             * +orderby(排序,可选ascending和descending两种方式,默认的是ascending)
             * +select(指定所选定的对象: 1. 整个数据项 2.数据项的一个字段 3.数据项中几个字段组成的新对象(或类似其他值))
            */
            //eg:查询Age>18的对象
            var query = from r in Students
                        where r.Age > 18
                        orderby r.Age
                        select r;
            //对应的lambda表达式
            var query_1 = Students.Where(r => r.Age > 18).OrderBy(r => r.Age).Select(r=>r);
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query));
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_1));

            //linq查询为延迟查询,只需构造一次查询语句,可以多次使用,在调用时才会执行
            //eg:为集合添加一个对象,使用之前的查询
            Students.Add(new Student(4,"赵五",19));
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query));

            //join 结合两个或更多集合中的数据,创建一个临时的对象集合
            //eg:查询选修生物课程的学生名,通过相同的id判断
            var query_2 = from r in Students
                    join c in Courses on r.Id equals c.Id
                    where c.CourseName == "生物"
                    select r.Name;
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_2));

            // 利用OfType方法可以把特定类型数据筛选出来
            //eg:从下列数组中获取int类型的数据
            object[] objList = new object[] { 1,"张三",2,3,"李四"};
            var query_3= objList.OfType<int>();
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_3));

            //多级排序,越靠前,优先级越高
            //eg:先按年龄排序,年龄一样按ID排序
            var query_4 = from r in Students
                          orderby r.Age, r.Id
                          select r;
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_4));

            //group子句可以让你把select的结果按指定的键(key)进行分组 ,每一个分组由一个叫做键的字段区分,分组本身是可枚举类型的并且可以枚举它的项
            //into子句可以接受查询的一部分结构并赋予一个名字,从而可以在查询的另一部分中使用
            //eg:通过课程名进行分组,选出成员数量大于2的组,形成新的集合
            var query_5 = from r in Courses
                          group r by r.CourseName
                          into g
                          orderby g.Count() descending, g.Key
                          where g.Count() > 2
                          select new { courseName = g.Key, count = g.Count() };
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_5));

            //通过Take()和Skip()实现只显示部分查询结果。
            //通过skip跳过指定数量的元素,再通过take提取固定长度元素,可实现分页
            //eg:查询Age>18,跳过第一个元素,取2个元素
            Students.Add(new Student(5, "孙六", 19));
            var query_6 = (from r in Students
                        where r.Age > 18
                        orderby r.Age
                        select r).Skip(1).Take(2);
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(query_6));

            /*
             * System.Linq 名称空间中的包含的类 ParallelEnumerable 可以分解查询的工作, 使其分布在多个线程上。
             * 尽管 Enumerable 类给 IEnumerable<T> 接口定义了扩展方法,但 ParallelEnumerable 类的大多数扩展方法是 ParallelQuery<TSource>类的扩展。
             * 一个重要的例外是 AsParallel() 方法,扩展 IEnumerable<TSource> 接口,返回 ParallelQuery<TSource>类,所以正常的集合类可以以并行方式查询。
             */
            //eg
            Console.WriteLine("构造大数据,耐心等待。。。");
            const int count = 100000000;
            var data = new int[count];
            for (int i = 0; i < count; i++)
            {
                data[i] = new Random().Next(40);
            }
            Console.WriteLine("构造完成,开始查询");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var query_7 = (from r in data
                          where r > 20
                          select r).Sum();
            stopwatch.Stop();
            Console.WriteLine($"正常运行耗时:{stopwatch.ElapsedMilliseconds}");
            stopwatch.Restart();
            var query_8 = (from r in data.AsParallel()
                           where r > 20
                           select r).Sum();
            stopwatch.Stop();
            Console.WriteLine($"并行运行耗时:{stopwatch.ElapsedMilliseconds}");

            /*对于并行ling而言,可利用System.Threading.CancellationTokenSource设置取消长时间的查询操作。
              通过.WithCancellation(Token)设置
              该查询在单独的线程中运行,在该线程中,捕获一个OperationCanceledException类型的异常。如果取消了查询就触发这个异常。
              在主线程中,调用CancellationTokenSource类的Cancel()方法可以取消任务
            */
            //eg
            var tokenSource = new CancellationTokenSource();
            Task.Run(() =>
            {
                try
                {
                    if (!tokenSource.IsCancellationRequested)
                    {
                        var query_9 = (from r in data.AsParallel().WithCancellation(tokenSource.Token)
                                       where r > 5
                                       select r).Sum();
                        Console.WriteLine($"查询结果:{query_9}");
                    }
                }
                catch (OperationCanceledException ex)
                {
                    Console.WriteLine("查询取消成功");
                    Console.WriteLine($"异常信息:{ex.Message}");
                }
               
            });
            Console.WriteLine("查询开始");
            Thread.Sleep(150);
            Console.WriteLine("150ms后执行取消并行查询");
            tokenSource.Cancel();

            // System.Collections.Concurrent.Partitioner.Create 可以手动创建分区器。
            //eg
            var query_10=(from r in Partitioner.Create(data,true).AsParallel()
                         where r > 5
                         select r).Sum();
            Console.WriteLine($"查询结果:{query_10}");


            //查找出现次数最多的元素
            int[] values = new int[] { 1, 2, 5, 2, 3, 5, 5, 3, 4, 6, 3, 3 };
            var query_11 = values.GroupBy(x => x).OrderByDescending(s => s.Count()).FirstOrDefault();
            Console.WriteLine($"出现次数最多的元素:{query_11.FirstOrDefault()}    次数:{query_11.Count()}");
        }

        private void GetDataSource()
        {
            Students = new List<Student>
            {
                new Student(1,"张三",18) ,
                new Student(2,"李四",19),
                new Student(3,"王麻子",20)
            };

            Courses = new List<Course>
            {
                new Course(1,"语文"),
                new Course(1,"数学"),
                new Course(1,"英语"),
                new Course(2,"语文"),
                new Course(2,"历史"),
                new Course(2,"生物"),
                new Course(3,"语文"),
                new Course(3,"化学"),
                new Course(3,"生物"),
            };
        }

    }

    class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public Student(int id, string name, int age)
        {
            Id = id;
            Name = name??null;
            Age = age;
        }
    }

    class Course
    {
        public int Id { get; set; }
        public string CourseName { get; set; }

        public Course(int id, string courseName)
        {
            Id = id;
            CourseName = courseName ?? null;
        }
    }
}

调用:

LinqHelper linqHelper = new LinqHelper();
linqHelper.Query();

执行结果:

参考:c# Linq查询 - DullFish - 博客园 (cnblogs.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值