LinQ的初步学习与总结

               嘿嘿,说起来ORM和LinQ,就感觉离我好遥远的,在学校是没有学习的,所以总感觉学习了LinQ就是大神,现在嘛,终于也体会一点,感觉LinQ只是初步学习,没有太难,当然以后使用在项目中就没有这样的简单啦,下面就全面的总结一下LinQ的其中一部分,LinQ有三部分:LinQ TO Object;LinQ TO SQL ;LinQ TO XML。而在这里我先来总结一下LinQ TO Object的学习吧

          一.初步认识LinQ to Object

        static void Main(string[] args)
        {//一个简单认识LinQ的小例子:
            int[] array = {1,2,3,4,5,6,7 };       //相当于数据源
            IEnumerable<int> everyarray = from n in array         //定义并存储查询
                                          where n > 3
                                          select n;
            foreach (var item in everyarray)             //执行查询
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }
        在主句库中我们可以看到一张张的表存放数据,而在程序中却与数据库相反,保存在类对象或者结构中的数据差异很大,因此没有通用的查询语句来从数据结构中获取数据,从对象获取数据的方法在这里我们就可以使用LinQ,可以轻松的查询对相集合。LinQ:语言集成查询,是.net框架的扩展,允许我们使用SQL查询数据库的方式来查询数据集合,使用LinQ可以从数据库,程序对象的集合以及XML文档中查询数据.
二.匿名类型
匿名类型就是创建无名类类型的特性,匿名类型经常用于LinQ查询的结果之中,创建匿名类型没有类名和构造函数,下面就演示一下匿名类型的对象创建表达式:
           var student = new {Name="下雨天",Age=20,Major="asp.net" };  //匿名对象初始化  在这里需要使用关键字var,强类型
            Console.WriteLine("{0},年龄:{1}、主修课程:{2}",student.Name,student.Age,student.Major);
            Console.ReadKey();

                匿名类型注意事项:

          匿名类型只能和局部变量配合使用,不能用于类成员
          匿名乐行没有名字,必须使用var关键字做为变量类型
          不能设置匿名类型对象的属性,而且编译器为匿名类型创建的属性是只读的

                三.查询语法和方法语法

                 LinQ查询时可以使用两种形式的语法:查询语法和方法语法。

        static void Main(string[] args)
        {
            int[] array = {2,3,4,56,73,4,23,34 };
            var nums = from n in array          //查询语法,看上去和SQL很像,使用查询表达式语法书写
                       where n > 10
                       select n;

            var num = array.Where(x=>x>10);          //方法语法,使用标准的方法调用

            int arr = (from n in array
                       where n > 10
                       select n).Count();           //两种形式的组合
            foreach (var item in nums)
            {
                Console.WriteLine(item);
            }
            foreach (var item in num)
            {
                 Console.WriteLine(item);
            }

            Console.WriteLine(arr);
            Console.ReadKey();
        }

              查询语法是声明式的,看上去和SQL语句很相似,查询语法使用查询表达式书写;而方法语法是命令式的,使用的是标准的方法调用,方法十一组交租标准查询运算符的方法。

                四.查询变量

               LinQ查询时间可以返回两种结果,一个是枚举,另一个是标量;枚举列表满足查询参数的项列表;标量满足查询条件的结果的某种摘要形式。

        static void Main(string[] args)
        {
            int[] array = {1,2,3,4,5,6,7,8,9 };
            IEnumerable<int> intlist = from n in array     //返回枚举数
                                       where n < 6
                                       select n;
            int nums = (from n in array                //返回一个整数
                          where n > 5
                          select n).Count();
            foreach (var item in intlist)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine(nums);

            Console.ReadKey();
        }

              如果查询表达式返回枚举,查询一直到处理枚举时间才会被执行,如果枚举被处理多次,查询就会被执行多次;如果查询表达式返回标量,查询立即执行,并且把结果保存在查询变量中。

               五.查询表达式的结构

               查询表达式子句必须按照一定的顺序出现,from子句select……group子句这两部分是必需的,其他可选;可以有任意多的from……let……where子句。

           1.from子句

        static void Main(string[] args)
        {
            int[] array = {10,23,33,44 };
            IEnumerable<int> fromlist = from item in array         //item为迭代变量
                                        where item < 30            //使用迭代变量
                                        select item;               //使用迭代变量
            foreach (var item in fromlist)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

           from子句,指定了要作为数据源使用的数据集合,它还引入了迭代矢量,迭代变量逐个表示数据源的每一个元素。Type时是集合元素的类型,这个可选,因为编译器可以从集合中推断类型。Item是迭代器的名字,Items是要查询的集合的名字,集合必须是可枚举类型,即:from type Item in Items。

           在这里需要注意的是:from子句和foreach语句很相似,但是还是有区别的:1.foreach语句命令式的指定了要从第一个到最后一个按照顺序的访问集合中的项,而from子句则声明似的规定集合中的每个=项都需要被访问,但没有假定以什么顺序;2.foreach语句在遇到代码时就执行某主体,而from子句不执行,它创建可查询的后台代码对象。只有在程序的控制流遇到访问查询变量的语句时,才会执行查询。 

           2.join子句以及什么是联结

           LinQ中的join子句和SQL中的JOIN子句很相似, LinQ接受两个集合然后创建一个新的集合,每个元素包含两个原始集合中的原始成员。而join用来联结两个集合,下面就了解下联结:

        public class Student        //初始化数组
        {
            public int sId;
            public string LastName;
        }
        public class Course
        {
            public int cId;
            public string CourseName;
        }
        static Student[] student = new Student[]{      //初始化数组
            new Student{LastName="下雨天",sId=1},
            new Student{LastName="晴天娃娃",sId=2},
            new Student{LastName="旋转音乐盒",sId=3},
       };
        static Course[] course = new Course[]{
            new Course{CourseName="asp.net",cId=1},
            new Course{CourseName="java",cId=1},
            new Course{CourseName="Linux",cId=2}
        };
        static void Main(string[] args)
        {
            var querylist = from s in student                      //student是第一个集合course是第二个集合,
                            join c in course on s.sId equals c.cId    // sId是第一个集合的项,cId是第二个集合的项
                            where s.LastName == "下雨天"              //在这里即使用了join子句,也可以看出来联结的语句结构
                            select c.CourseName;

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

                使用联结来结合两个或更多集合中的数据,联结操作结合两个集合然后创建一个临时的对象集合,每一个对象都包含原始集合中的所有字段;在这里需要注意的是,要使用关键字equals,而不能使用“==”运算符。

                3.查询主体中的from…let…where

          (1)from子句:第一个from子句是查询表达式必需的子句,第二个from子句是第一个子句的查询主体。

        static void Main(string[] args)
        {
            var groupa = new[] { 3, 4, 5, 6 };
            var groupb = new[] { 6, 7, 8, 9 };
            var nums = from a in groupa         //必需第一个from子句
                       from b in groupb          //查询主体的第二个from子句
                       where a > 4 && b <= 8
                       select new { a, b, sum = a + b }; //匿名类型对象
            foreach (var item in nums)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

                

          在这里select子句创建了一个匿名类型的对象。

         (2)let子句:let接受一个表达式的运算并且把他赋值给一个需要在其他运算中使用的标示符。

        static void Main(string[] args)
        {
            var groupa = new[] { 3, 4, 5, 6 };
            var groupb = new[] { 6, 7, 8, 9 };
            var num = from a in groupa         //必需第一个from子句
                      from b in groupb          //查询主体的第二个from子句 
                      let sum = a + b           //在新的变量中保持结果
                      where sum == 12
                      select new { a, b, sum };
            foreach (var item in num)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

               (3)Where子句:where子句根据之后的运算来去除不符合指定条件的项

        static void Main(string[] args)
        {
            var groupa = new[] { 3, 4, 5, 6 };
            var groupb = new[] { 6, 7, 8, 9 };
            var list = from a in groupa
                       from b in groupb
                       let sum = a + b
                       where sum >= 12
                       where a == 4
                       select new { a, b, sum };
            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

                需要注意的是:只要是在from……let……where部分中,查询表达式可以有任意多个where子句,一个项必须满足where子句才能在之后被过滤。

          (4)Orderby子句:order子句接受一个表达式并根据表达式按照顺序返回结果项

        static void Main(string[] args)
        {
            var student = new[] { 
            new {FirstName="",LastName="",Age=16,Major="asp.net"},
            new {FirstName="",LastName="",Age=19,Major="java"},
            new {FirstName="",LastName="",Age=20,Major="php"}
            };
            var query = from s in student
                        orderby s.Age         //根据age排序
                        select s;
            foreach (var s in query)
            {
                Console.WriteLine("{0}{1}:{2},主修:{3}", s.FirstName, s.LastName, s.Age, s.Major);
            }
            Console.ReadKey();
        }

                 在这里,可选的ascending和descending关键字设置了排序方向,orderby子句的默认排序是升序。我们可以使用ascending和descending关键字显式的设置元素的拍讯为升序或者降序,可以有多个任意子句,使用逗号隔开即可。

          (5)Select子句:制定所选对象的那部分应该被select。它可以指定:整个数据项,整个项的一个字段,数据项中整个字段组成的新对象。

 

        static void Main(string[] args)
        {
            var student = new[] {             //匿名类型的对象数组
            new {FirstName="",LastName="",Age=16,Major="asp.net"},
            new {FirstName="",LastName="",Age=17,Major="java"},
            new {FirstName="",LastName="",Age=20,Major="php"}
            };
            var query = from s in student
                        select s;
            foreach (var item in query)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

 

                   (6)查询中的匿名类型:查询结果中可以由原始集合的项,项的某些字段或匿名类型组成,然后如下所示:

        static void Main(string[] args)
        {
            var student = new[] {             //匿名类型的对象数组
            new {FirstName="",LastName="",Age=16,Major="asp.net"},
            new {FirstName="",LastName="",Age=17,Major="java"},
            new {FirstName="",LastName="",Age=20,Major="php"}
            };
            var query = from s in student
                        select new { s.FirstName, s.LastName, s.Major };//创建匿名类型
            foreach (var s in query)
            {
                Console.WriteLine("{0}{1}:{2}", s.FirstName, s.LastName, s.Major);
            }
            Console.ReadKey();
        }

                    (7)Group子句:group子句把select的对象根据一些标准进行分组。

        static void Main(string[] args)
        {
            var student = new[] {             //匿名类型的对象数组
            new {FirstName="",LastName="",Age=16,Major="asp.net"},
            new {FirstName="",LastName="",Age=16,Major="java"},
            new {FirstName="",LastName="",Age=20,Major="php"}
            };
            var query = from s in student
                        group s by s.Age;
            foreach (var s in query)         //枚举分组
            {
                Console.WriteLine("{0}", s.Key);
                foreach (var item in s)
                {
                    Console.WriteLine("     {0}{1}", item.FirstName, item.LastName);
                }
            }
            Console.ReadKey();
        }

                注意的事项主要有:如果项包含在查询的结果中,他们就可以根据某个字段的值进行分组,作为分组依据的属性叫做键;group子句返回的不是原始数据源中项的枚举,而是返回可以枚举已经形成的项的分组的可枚举类型;分组本身如果是可枚举类型,他们可以枚举实际的项。

           查询表达式返回的对象是从查询中枚举分组结果的可枚举类型,每一个分组由一个叫做键的字段区分,每一个分组本身是可枚举类型,他们可以枚举实际的项。

          (8)查询延续。into子句:查询延续可以接受查询的一部分结果并赋予一个名字,从而可以再查找的另一部分中使用

       static void Main(string[] args)
        {
            var groupa = new[] { 7, 4, 5, 6 };
            var groupb = new[] { 6, 7, 8, 9 };
            var query = from a in groupa
                        join b in groupb on a equals b
                        into groupc
                        from c in groupc
                        select c;
            foreach (var item in query)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

                 (9).标准查询运算符:这个共有40多个方法,简单的方法已经在昨天举例写过,这里就添加一个连接(http://www.cnblogs.com/dyxd/p/4187916.html),不再总结啦。写一下具体的分类:

                   

                  六.查询表达式和标准查询运算符

            var num = new int[] {3,6,4,8,10 };
            int numbers = (from n in num
                           where n < 7             //查询表达式
                           select n).Count();       //运算符
            Console.WriteLine("数量:{0}",numbers);
            Console.ReadKey();

                   标准查询运算符是进行查询的一组方法,每一个查询表达式还可以使用带标准查询运算符的方法的语法来编写。编译器把每一个查询表达式翻译成标准查询运算符的形式,由于所有查询表达式都被翻译成标准查询运算符,因此运算符可以执行由查询表达式完成的任何操作,而且所有查询表达式形式所不能提供的附加功能。当然,查询表达式和方法语法这两种表达式也可以组合。

           在这里还有委托作为参数以及LinQ预定义的委托类型,Lambda表达是参数在昨天已经总结过啦,嘿嘿,所以关于LinQ to Object就总结到这里,我总结的仅仅是初学者都能看懂的,还没有在项目中使用目前,希望以后在项目中使用时间我能够熟练的运用。

posted @ 2014-12-27 23:58  雪?  阅读(1644)  评论(7编辑  收藏  举报