C# 3.0 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};


  第一个属性的名字不会变,第二个会被重新命名。
来源:http://www.cnblogs.com/126/archive/2006/12/20/503519.html

加支付宝好友偷能量挖...


评论(0)网络
阅读(74)喜欢(0)Asp.Net/C#/WCF