C# 3.0入门系列(四)-之Select操作

转载 2007年09月28日 16:51:00
先给关注dlinq的朋友们道歉,最近工作实在忙,没有时间来写blog。从本节开始,我们讲dlinq语法咯。我们先从select子句讲起。看下面的例子。
    var q =
        from c 
in db.Customers
        select c.ContactName;

这是一个最简单的dlinq查询语句,查询得到联系人的名字。在这里,我需要提醒下大家的是,像这个语句只是个声明,dlinq并没有真正把数据取出来,只有当你需要该数据的时候,它才会帮你去取,这就是延迟加载(deferred loading)。如果,你想在声明的时候就希望dlinq帮你取到数据,你可以使用ToList() 或ToArray()方法。如上例。

        var q = (from c in db.Customers
                 select c.ContactName).ToArray();
        var q = (from c in db.Customers
                 select c.ContactName).ToList();

在这里,我还要提醒大家一点。dlinq返回的结果集是对象的集合,不是数据的。
 在dlinq执行的时候,它会先将上面的标准查询转换成dlinq的API(也有人叫级连方法),比如,下面语句

            var q =
                from c 
in db.Customers
                where c.City 
== "London"
                select c;

就会先被转化成 var q = db.Customers.Where(c=>c.City== "London").Select(c=>c); 也就是说,这两个语句是等价的。而后,dlinq会解析影射文件,根据dlinq的query语句,自动产生sql语句,并把sql送到sql server服务器,根据返回的数据集,创建相应的对象。在这里,你可能会对c=>c感到非常陌生。这是Lambda表达式(expression),你可以理解c为结果集里的任一对象,这对象的类型是和你结果集里元素类型是一致的 。这里理解起来可能困难。我们一起来理解下数据即是对象的概念。我相信这会帮我们理解Lambda表达式。

在dlinq之前,在java领域有Hibernate,在net领域有NHibernate技术,来实现object/relational 持久和查询服务。dlinq其实质上,是在吸收了众多技术的基础上,比他们更加强大的工具。数据即对象的含义有两层。第一,数据结构(表结构)即是类。可以描述为Table Schema--Class。第二,表里的数据即是变量,描述为Data--object(variable)。那么,我们在来理解Lambda表达式可能就容易些。刚才我们已经说了,var q = db.Customers.Where(c=>c.City== "London").Select(c=>c);将会返回Customers对象的集合,也就说,这个集合的每个元素就是一个Customer。Lambda表达式是对c# 2.0中的anonymous methods(匿名方法)的扩展。它更加简化匿名方法的实现形式。这里的c是一种隐式的声明,编译器会自动推断它的实际类型,也可以显示声明,比如,  var q = db.Customers.Where((Customer c) => c.City == "London").ToList();  Lambda表达式用=>符号跟随一个表达式,这个表达式,需要返回一个类型,其实质就是一个方法返回一个类型。它只是更加简洁的匿名方法。然后,where等操作符用它返回的这个类型做为参数。关于Lambda表达式的具体实现,我会在进阶部分详细讲解。这里不再赘述。

有一点要提醒大家的是,标准的查询语句,必须是select语句在最后,而级连表达式,各种操作符的位置并不是很重要。比如var q = db.Customers.Where(c=>c.City== "London").Select(c=>c); 可以写成var q = db.Customers.Select(c=>c).Where(c=>c.City== "London");它们两个是一样的,但是,标准查询就不可以换位子,select语句必须在最后。虽然在级连表达式,各种操作符的位置并不是很重要,但是他们还是有区别的。特别是在使用匿名类后,区别很明显。但万变不离其宗,我们只要记住,下一个操作符总是在上一个操作符所筛选的数据集的基础上进行筛选。这点,我会在以后的blog中,更加详细的说明。
在select语句中,另一个难点是匿名类。比如列子

            var q =
                from c 
in db.Customers
                select 
new {c.ContactName, c.Phone};

其实不光在select操作中有匿名类,其他操作中也有。让我们一起来理解下匿名类。上面的语句与
var q = db.Customers.Select(c=>new {c,ContactName,c.Phone});是等价的。匿名类是c# 3.0中新出现的特性。其实质是编译器根据用户定义,自动产生一个匿名的类,帮用户实现临时变量的储存。注意,是临时变量。大量使用匿名类会使程序可读性降低。匿名类还依赖于另外一个特性,就是在c# 3.0可以支持根据property来创建对象。比如,有类

    public class Person
    {
        
private string name;

        
public string Name
        {
            
get { return name; }
            
set { name = value; }
        }
    }

以前,我们只可以用构造函数来创建其对象,现在在3.0中支持用property来创建,即,可以用
 var d = new Person { Name = "s" }; 来创建对象。在这里,你可能还对var类型产生疑问。你可能以为c#3.0和javascript一样是弱类型的。其实var并不是c#3.0的类型,它是编译器的关键字,编译器根据实际变量的返回类型,自动推断类型。那么var c = null; 是无法编译通过,因为编译不知道null代表那个类型。所以,c#3.0还是强类型的。

现在3.0可以支持用property来创建对象了,那么就有了匿名类的出现。比如,var d = new { Name = "s" };编译器自动产生一个有property叫做Name的匿名类,然后按这个类型分配内存,并初始化对象。在这个地方,还有个问题,比如,var d = new {  "s" };是编译不通过的。因为,编译器不知道匿名类中的property的名字。但是,如果,        string c = "d";     var d = new { c}; 则是可以通过编译的。编译器会创建一个叫做匿名类带有叫c的property。

在dlinq中,比如new {c,ContactName,c.Phone});这里出现ContactName和Phone都是我们在影射文件中定义的和表中字段相对应的property。编译器在取会数据并创建对象时,会创建一个匿名类,这个类有两个属性,为ContactName和Phone,然后根据数据初始化对象。匿名类还有另外一种形式。

            var q =
                from e 
in db.Employees
                select 
new {Name = e.FirstName + " " + e.LastName, Phone = e.HomePhone};
这种形式和第一种不同的是,编译器会重命名property的名字。当然也可以把两种形式组合起来。
            var q =
                from p 
in db.Products
                select 
new {p.ProductID, HalfPrice = p.UnitPrice / 2};

第一个属性的名字不会变,第二个会被重新命名。
好,就先讲这几个,下节我会介绍几个更复杂的用法。  

C# 3.0 Dlinq介绍(四)-之Select操作

先给关注dlinq的朋友们道歉,最近工作实在忙,没有时间来写blog。从本节开始,我们讲dlinq语法咯。我们先从select子句讲起。看下面的例子。     var q =         fr...
  • iamdll
  • iamdll
  • 2014年03月21日 15:17
  • 281

C# 3.0 入门系列(一)

谈到dlinq,就不得不先说linq。让我们先看看什么是linq。linq是 Language Integrated Query的缩写。那么事实上dlinq就是 Database Language I...
  • Van_chan
  • Van_chan
  • 2014年06月25日 15:41
  • 262

C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。

C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。 标签: c#objectnewlineexceptionbytestring 2010-05-17 01:10 117...
  • kasama1953
  • kasama1953
  • 2016年06月27日 14:58
  • 3798

“Ceph浅析”系列之四Ceph的结构

本文将从逻辑结构的角度对Ceph进行分析。 4.1    Ceph系统的层次结构         Ceph存储系统的逻辑层次结构如下图所示[1]。         自下向上,可以将Ceph系统...
  • qq_24916117
  • qq_24916117
  • 2015年12月30日 20:42
  • 529

四轴飞行diy全套入门教程(从最基础的开始)

首先声明本人也是菜鸟,此教程就是从一个菜鸟的角度来讲解,现在论坛上的帖子都突然冒很多名词出来,又不成体系,我自己开始学的时候往往一头雾水,相信很多新手也一样。所以在这个帖子里面,我都会把自己遇到的疑惑...
  • J_1234567890
  • J_1234567890
  • 2016年07月07日 15:15
  • 7081

手把手入门神经网络系列(1)_从初等数学的角度初探神经网络

作者: 龙心尘&&寒小阳 时间:2015年11月。 出处:http://blog.csdn.net/longxinchen_ml/article/details/50082873, 声明:版权...
  • yaoqiang2011
  • yaoqiang2011
  • 2015年11月29日 22:11
  • 22090

C# 串口操作系列(4) -- 协议篇,文本协议数据解析

C# 串口操作系列(4) -- 协议篇,文本协议数据解析 分类: 通讯类库设计2010-06-09 01:50 9356人阅读 评论(26) 收藏 举报 c#uiobjectstr...
  • zb872676223
  • zb872676223
  • 2013年07月24日 18:35
  • 1197

SpringBoot入门系列:第一篇 Hello World

出于对作者的尊重和感谢,原文地址为 http://blog.csdn.net/lxhjh/article/details/51711148    跟随SpringBoot的文档(http://...
  • sosfnima
  • sosfnima
  • 2016年07月22日 11:52
  • 3315

C#操作Sqlite快速入门

http://www.cnblogs.com/greatverve/archive/2011/04/28/sqlite-start.html Sqlite不需要安装即可使用。 Sqli...
  • lanshengsheng2012
  • lanshengsheng2012
  • 2013年11月20日 12:46
  • 1810

Jenkins入门系列之——01第一章 Jenkins是什么?

说明:Jenkins折腾了好几个月了,打算写个系列记录下。有时间会尽量更新的。 第一章 Jenkins是什么? Jenkins 是一个可扩展的持续集成引擎。 主要用于: ...
  • lin___
  • lin___
  • 2016年09月14日 09:32
  • 931
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C# 3.0入门系列(四)-之Select操作
举报原因:
原因补充:

(最多只允许输入30个字)