黑马程序员 LINQ(1) 介绍LINQ、语法 总结

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

1.什么是LINQ:
LINQ(link)代表语言集成查询(Language Integrated Query).
LINQ是.NET框架的扩展,它允许我们以数据库查询的方式查询数据集合。
LINQ是.NET框架的扩展,它允许我们以数据库查询的方式查询集合。
使用LINQ,你可以从数据库、程序对象的集合以及XML文档中竺查询数据。

2.匿名类型:
创建匿名类型的变量和对象初化器相似,使用相同的形式,但是没有类名和构造方法。如下:
 var student = new { LName = "Jones", FName="Mary", Age=19, Major="History"};
 Console.WriteLine("{0} {1},Age:{2},Major:{3}",
     student.LName, student.FName, student.Age, student.Major);
可以像访问具名类型的成员那样访问实例的成员。
匿名类型的重要事项:
匿名类型只能和局部变量配合使用,不能用于类成员。
由于匿名类型没有名字,我们必须使用var关键词作为变量类型。
匿名类型对象初始化器三种形式:
赋值形式,简单标识符和成员访问表达式。后两种形式叫做投影初始化器。投影初始化器必须定义在匿名型型声明之前。
   class Other
    {
        public static string Name = "Jones Mary";
    }

    class Program
    {
        static void Main(string[] args)
        {
            string Major = "History";

            var student = new { Age = 19, Name=Other.Name, Major};
            Console.WriteLine("Name:{0},Age:{1},Major:{2}",
                student.Name, student.Age, student.Major);
        }
    }

3.查询语法和方法语法
查询语法是声明形式的,看上去和SQL语句很相似。
方法语法是命令形式的,它使用的是标准的方法调用。方法是一组叫做标准查询运算方法。
在一个查询中也可以组合两种形式。
int[] numbers ={2, 5, 28, 31, 17, 16, 42};
var numsQuery = from n in numbers  //查询语法
  where n < 20
  select n;
var numsMetod = numbers.Where(x => x<20); //方法语法
var numsCount = (from n in numbers  //两种形式组合
  where n < 20
  select n).Count();
4.查询变量
LINQ查询可返回两种类型的结果——一个枚举,一个标量的单一值。
如果查询表达式返回枚举,查询一直到处理枚举时才会被执行。
如果查询表达式返回标量,查询立即执行,并且把结果保存在查询变量中。

5.查询表达式的结构
查询表达式由查询体后的from子句组成。查询表达式重要事项如下:
子句必须按照一定的顺序出现。from子句和select...group子句这两部分是必须的,其他子句是可选的。
在LINQ查询表达式中,select子句在表达式最后。
可以有任意多的from...let...where子句。
整个语句如下:
from... //必须的
from...
let...
where...
orderdy...
select... //必须的
group...
into...  //查询附加部分
5.1 from子句的语法如下.
from Type Item in Items
Type是集合中元素的类型。这是可选的,因为编译器可以从集合来推断类型。
Item是迭代变量的名字。
Items是要查询的集合的名字。集合必须是可枚举的。
5.2 join子句的语法
join Identifier in Collection2 on Field1 equals Field2
联结操作接受两个集合然后创建一个临时是对象集合,每一个对象包含原始集合对象中的所有字段。
使用连接来结合两个或更多集合中的数据
示例:
var query = from s in students
     join c in studentsInCourses on s.StID equals c.StID
什么是联结:LINQ中的联结接受两个集合然后创建一个临时的对象集合,每一个元素包含两个原始集合中的原始成员。
5.3 查询主体中的from...let...where片段
 from子句:
 我们看到查询表达式必须的from子句开始,后面跟的是查询主体。主体本身可以从任何数量的其他from子句开始,每一个from子句都指定了一个额外的源数据集合并引入了要在之后运算的迭代变量,所有from子句的语法和含义都是一样的。
示例
  static void Main(string[] args)
        {
            int[] groupA = { 3, 4, 5, 6 };
            int[] groupB = { 6, 7, 8, 9 };

            var someInts = from a in groupA  //必须的第一个from子句
                           from b in groupB  //查询主体的第一个子句
                           where a > 4 && b <= 8
                           select new { a, b, sum = a + b}; //利用前面的临时集合创建一个匿名类型对象

            foreach (var a in someInts)
                Console.WriteLine(a);

            Console.ReadKey();
        }
 let子句:
let子句接受一个表达式的运算并且把它赋值给一个需要在其他运算中使用的标识符。
let Identifier = Expression
示例:
        static void Main(string[] args)
        {
            int[] groupA = { 3, 4, 5, 6 };
            int[] groupB = { 6, 7, 8, 9 };

            var someInts = from a in groupA
                           from b in groupB
                           let sum = a + b
                           where sum == 12  //在新的变量中保存结果
                           select new { a, b, sum};

            foreach (var a in someInts)
                Console.WriteLine(a);

            Console.ReadKey();
        }
 where子句:
where子句根据这后的运算来除不符合指定条件的项。语法如下:
where BooleanExpression
示例.
        static void Main(string[] args)
        {
            int[] groupA = { 3, 4, 5, 6 };
            int[] groupB = { 6, 7, 8, 9 };

            var someInts = from int a in groupA
                           from int b in groupB
                           let sum = a + b
                           where sum >= 11   //条件1
                           where a == 4     //条件2
                           select new { a, b, sum};


            foreach (var a in someInts)
                Console.WriteLine(a);

            Console.ReadKey();
        }


5.4 orderby子句
orderby子句接受一个表达式并根据表达式依次返回结果项。语法如下:
orderby Experssion {ascending descending} //大括号中可选
order子句的默认排序是升序。然而,我们可以使用ascending和descending关键词显式地设置元素的排序为升序或降序
可以有任意多个子句,它们必须使用逗号分隔。
示例:。
 static void Main(string[] args)
        {
            var students = new[]
            {
                new { LName="Jones",  FName="Mary", Age=19 },
                new { LName="Smith",  FName="Bob",  Age=20 },
                new { LName="Fleming",FName="Carol",Age=21 }
            };

            var query = from student in students
                        orderby student.Age
                        select student;
            foreach (var s in query)
            {
                Console.WriteLine("{0},{1}:{2}", s.LName, s.FName, s.Age);
            }

            Console.ReadKey();
        }

5.5 select...group子句
select子句指定所选对象的哪部分应该被select.它可以指定整个数据项,数据项的一个字段,数据项中几个字段组成的新对象。
group...by子句是可选的,用来指定选择的项如何被分组。
语法。
select Expression group Expression1 by Expression2

5.6 查询中的匿名类型。
查询结果可以由原始集合的项、原始集合中项的一些字段或匿名类型组成。
我们可以通过在select子句中把希望在类型中包括的字段以逗号分隔,并以大括号进行包围来创建来创建匿名类型。

5.7 group子句
group子句把select的对象根据一些标准进行分组。重要事项如下。
如果项包含在查询的结果中,它们就可以根据某个字段的值进行分组。作为分组依据的项叫做键。
和select子句不同,group子句不从原始的数据源中返回可枚举项的可枚举类型,而是返回可以枚举已经形成的项的分组的可枚举类型。
分组本身是可枚举类型,它们可以枚举实际的项。
语法的一个示例如下。
group student by student.Gender;
示例:
      static void Main(string[] args)
        {
            var students = new[]
            {
                new { Name="Tom", Age=19, Gender="男"},
                new { Name="Jin", Age=20, Gender="女"},
                new { Name="Bob", Age=21, Gender="男"}
            };

            var query = from student in students
                        group student by student.Gender;                       

            foreach (var s in query)
            {
                Console.WriteLine(s.Key);

                foreach (var t in s)
                    Console.WriteLine("    {0}:{1}", t.Name, t.Age);
            }

            Console.ReadKey();
        }
注意:
从查询表达式返回的对象是从查询中枚举分组结果的可枚举类型。
每一个分组由一个叫做键的字段区分。
每一个分组本身是可枚举类型并且可以枚举它的项。

5.8查询延续
查询延续子句可以接受查询的一部分结果并赋予一个名字,从而可以在查询的另一部分使用。
示例
  static void Main(string[] args)
        {
            var groupA = new[] { 3, 4, 5, 6};
            var groupB = new[] { 4, 5, 6, 7};

            var someInts = from a in groupA
                           join b in groupB on a equals b
                           into groupAsndB
                           from c in groupAsndB
                           select c;
            foreach (var a in someInts)
                Console.Write("{0} ", a);

            Console.ReadKey();
        }

6.标准查询运算符。
标准查询运算由一系列叫做API的方法组成,它能让我们查询任何.NET数组或集合。重要特性如下。
被查询的集合对象叫序列,它必须实现IEnumerable<T>接口,T是类型。
标准查询运算符使用方法语法。
一些运算符返回IEnumerable对象(或其他)序列,而其他的一些运算符返回标量。返回标量的运算符立即执行,面返回替代可枚举类型对象的值会被延迟迭代。
示例:注意,用作方法的运算符直接作用于序列对象,在这里就是numbers数组。
返回类型不是IEnumerable对象,而是int.
        static void Main(string[] args)
        {
            int[] numbers = new[] { 2, 4, 6};

            int total = numbers.Sum();  //返回int.
            int howMany = numbers.Count();

            Console.WriteLine("Total:{0},Count:{1}", total, howMany);

            Console.ReadKey();
        }
实际编译器把查询表达式翻译成了标准查询运算符形式。

标准查询运算符的签名:System.Linq.Enumerable类声明了标准查询运算符方法。然而这些方法不仅仅是一些方法,它们是扩展了IEnumerable<T>泛型的扩展方法。
那么就还可以用扩展方法来调用。如下。
int[] intArray = new[] { 3, 4, 5, 6, 7, 9};
var count = Enumerable.Count(intArray);

委托作为参数。
每一个运算符的第一个参数是IEnumerable<T>对象的引用,之后的参数可以是任何类型,很多去处符接受泛型委托作为参数。泛型委托用于给运算符提供用户自定义的代码。
运用。
        static void Main(string[] args)
        {
            int[] intArray = new[] { 3, 4, 5, 6, 7, 9 };
 //接受一个寻找奇数的Lanmbda表达赋给第二个委托变量,每个元素处理前先调用这个函数。
//原型:public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
            var count = intArray.Count(n => n % 2 == 1);

            Console.WriteLine("Count of odd numbers:{0}",count);

            Console.ReadKey();
        }

LINQ预定义的委托类型。
LINQ定义了两套泛型委托方法与标准查询运算符一起使用,这它们就Func委托和Action委托,各有17个成员。
我们用做实参的委托对象必须是这些类型或这些形式这一。
TR代表返回值,并且总是在类型参数列表中的最后一个。
public delegate TR Func<out TR>       ();
public delegate TR Func<in T1, out TR>         (T1 a1);
public delegate TR Func<in T1, in T2, out TR>     (T1 a1, T2 a2);
public delegate TR Func<in T1, in T2, in T3, out TR>(T1 a1, T2 a2, T3 a3);
......
public delagate void Action   ();
public delagate void Action<in T1>  ();
public delagate void Action<in T1, in T2> ();
public delagate void Action<in T1, in T2, in T3>();
......
使用委托参数的示例。
    class Program
    {
        static bool IsOdd(int x)
        {
            return x % 2 == 1;
        }

        static void Main(string[] args)
        {
            int[] intArray = new[] { 3, 4, 5, 6, 7, 9 };

            Func<int,bool> MyDel = new Func<int,bool>(IsOdd);
            var count = intArray.Count(MyDel);

            Console.WriteLine("Count of odd numbers:{0}",count);

            Console.ReadKey();
        }
    }
使用Lambda表达式参数的示例.
我们可以使用更简洁的更局部化的方法来给运算符提供代码,那就是Lambda表达式。
上面的示例可以改为
...
var count = intArray.Count(n => n % 2 == 1);
...
如下所示,我们也可以使用匿名方法来替代lambda表达式,这两种方法等价,比较累赘,没Lambda好。
 var count = intArray.Count(delegate(int x)
            {
                return x % 2 == 1;
            });

 

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值