C#学习(六)之LINQ

  这个星期章老师讲授了.Net开发的相关知识,如LINQ,XML,MVC等,因为我正在上数据库这门课,所以我今天就主要记录一下LINQ的学习。

  首先介绍一下基础知识。

  LINQ,语言集成查询(Language Integrated Query)是一组用于C#和Visual Basic语言的扩展。它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据。

  LINQ的关键词有:from, select, in, where, group by, orderby, …十分类似于SQL数据库,易于入门。

  LINQ的写法:

  (1) from 临时变量 in 实现IEnumerable<T>接口的对象

  where条件表达式

  [orderby 条件]

  [group by 条件]

  select 临时变量中被查询的值

  (2) 实现IEnumerable<T>接口的对象.LINQ方法名(lambda表达式)。如:

  string input = "hello world";

  int count = input.Count(w=>w == ‘o‘); //查询字母o出现的次数

  需要注意的是能够使用LINQ的对象需要实现IEnumerable<T>接口。并且LINQ的查询表达式是在最近一次创建对 象时才被编译的。

  LINQ的命名空间(.NET Framework):System.Linq;

  为了更好的学习LINQ,我们有必要了解隐匿类型Lambda表达式以及IEnumerable 接口

  隐式类型,使用var关键字创建,C#编译器会根据用于初始化局部变量的初始值推断出变量的数据类型,var可代替任何类型。当我们无法确定自己将用的是什么类型,就可以使用var。代码示例如下:

1  var a = 1; //int a = 1;
2  var b = "123";//string b = "123";
3  var myObj = new MyObj();//MyObj myObj = new MyObj()

  上面的每行代码,与每行代码后面的注释,起到的作用是完全一样的。也就是说,在声明一个变量(并且同时给它赋值)的时候,完全不用指定变量的类型,只要一个var就解决问题了。而且这样写不会影响性能!

  使用var定义变量时有以下四个特点:

  1.必须在定义时初始化。也就是必须是var s = “abcd”形式,而不能是如下形式:

  var s;

  s = “abcd”;

  2. 一但初始化完成,就不能再给变量赋与初始化值类型不同的值了。

  3. var要求是局部变量。

  Lambda表达式只是用更简单的方式来书写匿名方法,从而彻底简化.NET委托类型的使用。

  Lambda表达式在C#中的写法是“arg-list => expr-body”,“=>”符号左边为表达式的参数列表,右边则是表达式体(body)。参数列表可以包含0到多个参数,参数之间使用逗号分割。

  IEnumerable<T>泛型接口支持在制定数据集合上进行迭代操作。它定义了一组扩展方法,用来对数据集合中的元素进行遍历、过滤、排序、搜索等操作。我们每次针对集合类型编写foreach代码块,都是在使用迭代器。这些集合类型都实现了IEnumerable接口。迭代器的优点是,假设我们需要遍历一个庞大的集合只要集合中的某一个元素满足条件就完成了任务。

  本次学习记录数据采用数据库实验课上老师所给数据,数据如下:

  三张表
  Sailors(int sid, string sname, int rating, int age),sid表示水手的编号,sname表示水手的姓名,rating表示水手的级别,age表示水手的年龄。
  Boats(int bid,string bname,string color),其中bid表示船的编号,bname是船的名字,color是船的颜色。
  Reserves(int sid, int bid, string rdate),Reserves中记录水手在哪天定了那只船,其中sid是指向Sailors的外关键字,bid是指向Boats的外关键字。

  sailors 表
  "22","dustin",7,45
  "29","brustus",1,33
  "31","lubber",8,56
  "32","andy",8,26
  "58","rusty",10,35
  "64","horatio",7,35
  "71","zorba",10,35
  "74","horatio",9,35
  "85","art",3,26
  "86","john",1,17
  "95","bob",3,64
  "96","frodo",3,26
  "98","tom",3,17

  Boats 表
  "101","A","red"
  "102","B","green"
  "103","C","blue"
  "104","D","white"
  "105","E","red"
  "106","F","blue"
  "107","G","green"

  Reserves 表
  "22","101","2010-01-08"
  "22","102","2010-01-09"
  "29","103","2010-01-09"
  "31","102","2010-02-11"
  "22","104","2010-03-08"
  "22","103","2010-03-10"
  "32","105","2010-03-11"
  "32","106","2010-03-18"
  "32","102","2010-03-19"
  "58","104","2010-03-20"
  "64","105","2010-03-20"
  "95","101","2010-04-02"
  "85","102","2010-04-05"
  "22","101","2010-04-07"
  "22","105","2010-05-01"
  "22","106","2010-06-18"
  "22","107","2010-07-09"
  "31","106","2010-08-06"
  "32","105","2010-08-06"
  "29","104","2010-08-07"
  "64","103","2010-09-05"
  "58","102","2010-09-09"
  "64","104","2010-11-03"
  "64","105","2010-11-04"
  "31","106","2010-12-06"

  下面开始实践。

  首先是表的属性创建,代码如下:

 1 public class Sailors
 2     {
 3         public int sid { get; set; }
 4         public string sname { get; set; }
 5         public int rating { get; set; }
 6         public int age { get; set; }
 7         // Overrides the Object.ToString() to provide a
 8         // string representation of the object properties.
 9         public override string ToString()
10         {
11             return string.Format("{0} {1} {2} {3}",
12                         sid, sname, rating, age);
13         }
14     }
15
16 public class Boats
17     {
18         public int bid { get; set; }
19         public string bname { get; set; }
20         public string color { get; set; }
21         // Overrides the Object.ToString() to provide a
22         // string representation of the object properties.
23         public override string ToString()
24         {
25             return string.Format("{0} {1} {2}",
26                         bid, bname, color);
27         }
28     }
29
30 public class Reserves
31     {
32         public int sid { get; set; }
33         public int bid { get; set; }
34         public string rdate { get; set; }
35         // Overrides the Object.ToString() to provide a
36         // string representation of the object properties.
37         public override string ToString()
38         {
39             return string.Format("{0} {1} {2}",
40                         sid, bid, rdate);
41         }
42     }

  表的属性由对应类的数据表示,并用ToString函数输出一条记录数据。

  

  下面进行数据初始化,以Sailors表为例:

 1 private static List<Sailors> createSailors()
 2         {
 3        //将数据储存在list中
 4             List<Sailors> sailors = new List<Sailors> {
 5                 new Sailors{ sid = 22,sname = "dustin",rating = 7, age= 45},
 6                 new Sailors{sid = 29,sname = "brustus",rating = 1, age = 33},
 7                 new Sailors{ sid = 31 ,sname = "lubber",rating = 8,age = 56 },
 8                 new Sailors { sid = 32, sname = "andy", rating = 8,age = 26},
 9                 new Sailors { sid = 58, sname = "rusty", rating = 10,age = 35},
10                 new Sailors { sid = 64 , sname = "horatio", rating = 7,age = 35},
11                 new Sailors { sid = 71,sname = "zorba", rating = 10, age = 35},
12                 new Sailors { sid = 74, sname = "horatio", rating = 9,age = 35},
13                 new Sailors { sid = 85, sname = "art", rating = 3,age = 26 },
14                 new Sailors { sid = 86,sname = "john", rating =  1,age = 17},
15                 new Sailors { sid = 95,sname = "bob", rating = 3,age= 64},
16                 new Sailors { sid = 96,sname = "frodo", rating = 3 , age = 26},
17                 new Sailors { sid = 98,sname = "tom",rating = 3,age = 17},
18             };
19             return sailors;
20         }

  

  下面开始本次学习记录的重头戏,查询语法

  首先来个简单的示例,查询名字为lubber的水手的编号,代码如下:

  

 1 public class Tester
 2     {
 3         static void Main()    // Main program
 4         {
 5             //初始化数据
 6             List<Reserves> reserves = new List<Reserves>(createReserves());
 7             List<Sailors> sailors = new List<Sailors>(createSailors());
 8             List<Boats> boats = new List<Boats>(createBoats());
 9        //查询语句
10             IEnumerable<Sailors> result = from sailor in sailors  //指定范围变量和数据源
11                                           where sailor.sname == "lubber"  //筛选条件
12                                           select sailor;  //指明需要提取的数据,即映射
13             foreach (Sailors a in result)
14             {
15                 Console.WriteLine(a.ToString());
16             }
17
18
19              Console.ReadKey();
20          }
21         ......
22     }    

  输出如下:

  是不是很简单?

  上面代码7行的IEnumerable<Sailors>和13行的Sailors也可改成var匿名类型,即

1 var result = from sailor in sailors
2              where sailor.sname == "lubber"
3              select sailor;
4  foreach (var a in result)
5             {
6                 Console.WriteLine(a.ToString());
7             }           

  输出不变,由此可见匿名类型给我们带来的极大便利。

  下面介绍联系各个表的join关键字,其基本形式是:[data source 1] join [data source 2] on [join condition],如查找定了103号船的水手的信息 就需要查询Sailors和Reserves两张表,代码如下:

 1 .....
 2 var result = from sailor in sailors
 3              join reserve in reserves on sailor.sid equals reserve.sid  //join后跟数据源与条件
 4              where reserve.bid == 103
 5              select sailor;
 6 foreach (var a in result)
 7         {
 8              Console.WriteLine(a.ToString());
 9         }
10 .....            

  输出如下:

  加入更多的表依然是按上面添加join语句即可。

  

  下面是结果的排序,使用orderby关键字,示例如下:

 1 ......
 2 var result = from sailor in sailors
 3              join reserve in reserves on sailor.sid equals reserve.sid
 4              where reserve.bid == 103
 5              orderby sailor.age//按水手年龄排序
 6              select sailor;
 7 foreach (var a in result)
 8       {
 9           Console.WriteLine(a.ToString());
10        }
11 .......

  输出结果如下:

  

  我们可以注意到结果按年龄(最后一项记录)升序排列,即LINQ默认的排序是升序的,要改成讲叙的只需在orderby语句行的最后加上descending关键字即可,如 orderby sailor.age descending 即可实现目的。

  下面谈一下分组查询,使用关键字group,by。如查询相同等级(rating)的水手姓名,代码如下:

 1 .....
 2 var result = from sailor in sailors
 3              orderby sailor.rating
 4              group sailor by sailor.rating;
 5
 6 foreach (var gp in result)
 7       {
 8          Console.WriteLine("{0}", gp.Key); //gp.Key是分组查询的关键字,即sailor.rating 9          foreach (var a in gp)
10          Console.WriteLine("\t{0}", a);
11       }
12 .....

  输出如下:

 

  

  最后说一下LINQ中的Lambda表达式。比如上面第一个查询操作就可以用Lambda表达式写成下列形势:

1 ......
2 var result = sailors.Where(sailor => sailor.sname == "lubber")
3              .Select(sailor => sailor);
4
5 foreach (var a in result)
6     {
7       Console.WriteLine(a.ToString());
8     }
9 ......

  

  本次学习记录到此为止,有机会我会添加新领悟的东西进去。

  望各位老师大牛不吝赐教!

 

时间: 2024-11-05 09:35:36

C#学习(六)之LINQ的相关文章

C#多线程学习(六) 互斥对象

C#多线程学习(六) 互斥对象 如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先等车,然后上车,最后下车.当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车.而线程与Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待Mutex对象被释放,如果它等待的Mutex对象被释放了,它就自动拥有这个对象,直到它调用Mute

Beaglebone Back学习六(Can总线测试)

Can总线测试 1 Can总线 控制器局域网 (Controller Area Network, 简称 CAN 或 CANbus)是一种通信协议,其特点是允许网络上的设备直接互相通信,网络上不需要主机(Host)控制通信.是由研发和生产汽车电子产品著称的德国BOSCH公司开发了的,并最终成为国际标准(ISO11898).CAN总线原理是通过CAN总线.传感器.控制器和执行器由串行数据线连接起来.它不仅仅是将电缆按树形结构连接起来,其通信协议相当于ISO/OSI参考模型中的数据链路层,网络可根据协

JBPM学习(六):详解流程图

概念: 流程图的组成: a. 活动 Activity / 节点 Node b. 流转 Transition / 连线(单向箭头) c. 事件 1.流转(Transition) a) 一般情况一个活动中可以指定一个或多个Transition i. 开始活动(Start)中只能有一个Transition. ii. 结束活动(End)中没有Transition. iii. 其他活动中有一条或多条Transition b) 如果Transition只有一个,则可以不指定名称(名称是null):如果有多个

Cmdlet开发与学习(六)

之前的内容主要是关于cmdlet开发的,下面要将的内容,是关于在应用程序中集成PowerShell引擎. 运行空间和管道       Runspace类是PowerShell引擎API的重要组成部分,Runspace实例代表一个PowerShell执行引擎实例,其中包含自己的一系列变量,驱动器映射,函数等.这些资源统称为运行空间的"会话状态". 创建并调用Pipeline类的实例,我们就可以在运行空间中使用命令行.Pipeline类实例代表PowerShell命令行对象,其中包含各种命

程序设计入门学习六步曲

初学者遇到最多的困惑是:上课也能听懂,书上的例题也能看明白,可是到自己动手做编程时,却不知道如何下手.发生这种现象的原因有三个: 一.所谓的看懂听明白,只是很肤浅的语法知识,而我们编写的程序或软件是要根据要解决问题的实际需要控制程序的流程,如果你没有深刻地理解C语言的语句的执行过程(或流程),你怎么会编写程序解决这些实际问题呢? 二.用C语言编程解决实际问题,所需要的不仅仅是C语言的编程知识,还需要相关的专业知识.例如,如果你不知道长方形的面积公式,即使C语言学得再好你也编不出求长方形的面积的程

Spark学习六:spark streaming

Spark学习六:spark streaming 标签(空格分隔): Spark Spark学习六spark streaming 一概述 二企业案例分析 三Spark streaming的工作原理 四textFileStreaming的应用 四企业中的开发方式 五总结 一,概述 一个简单的实例 1,安装nc nc -lk 9999 2,启动应用 ./bin/run-example streaming.NeworkWordCount localhost 9999 二,企业案例分析 需求: 实时统计

TweenMax动画库学习(六)

目录            TweenMax动画库学习(一)            TweenMax动画库学习(二)            TweenMax动画库学习(三)            TweenMax动画库学习(四)            TweenMax动画库学习(五)              TweenMax动画库学习(六)  上一节我们主要聊了TweenMax动画库中的currentLabel():获取当前状态.getLabelAfter():获取下一个状态.getLabel

springMVC3学习(六)--SimpleFormController

SimpleFormController提交表单流程例如以下: login.jsp <form action="login" method="post"> 用户名:<input type="text" name="username"/></br> 密码:<input type="password" name="password"/><

Oracle学习(六):子查询

1.知识点:可以对照下面的录屏进行阅读 SQL> --子查询所要解决的问题:问题不能一步求解 SQL> --查询工资比SCOTT高的员工信息 SQL> --(1)使用普通方法 SQL> --1. SCOTT的工资 SQL> select sal from emp where ename='SCOTT'; SQL> --2. 查询比3000高的员工 SQL> select * 2 from emp 3 where sal>3000; SQL> --(2)

Jetty学习六:配置连接器

连接器配置概览 连接器用于接收网络连接,配置一个连接器需要配置: 1)连接器的网络参数(例如:端口): 2)连接器使用的服务(例如:executors,schedulers): 3)为接收连接而初始化和配置协议的连接工厂. Jetty主要使用的连接器类型为ServerConnector. 标准Jetty发布使用下面的Jetty XML文件创建和配置连接器: 1)jetty-http.xml 初始化一个ServerConnector,用于接收HTTP连接(可以被升级到WebSocket连接). 2