Juvy

I Believe Persistence.

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一·前言

Linq 英文全称Language Integrated Query,它提供了C#编程语言中的查询语法,可以使用相同的语法访问不同的数据源。并且Linq还提供了不同数据源的抽象层,所以可以使用相同的语法。本次笔记的主要内容如下:

● 用List<T>在对象上执行传统查询
● 扩展方法
● λ表达式
● LINQ 查询
● 标准查询操作符
● 表达式树
● LINQ 提供程序

 

一。用List<T>在对象上执行传统查询

首先我们来看一个最简单的例子,请看下面的代码:

            List<string> strList = new List<string>();

            strList.Add("AAA");

            strList.Add("BABB");

            strList.Add("ACCC");

            strList.Add("BBB");

            strList.Add("CCC");

            var res = strList.FindAll(delegate(string s) { return s.Contains("A"); });

            res.Sort(delegate(string a, string b) { return a.CompareTo(b); });

            this.GridView1.DataSource = res;

            this.GridView1.DataBind();

这段代码是从strList中查找所有包含字母A的记录,并且将得到的结果进行进行从小到大的排序(如果将return a.CompareTo(b); 换成return b.CompareTo(a);结果则是从大到小的顺序进行排列了)。相信很多人用过这样的方式来对结果集进行过滤和排序操作。但是如果你想在任何集合都可以使用这两个方法,那你就可能会使用到扩展方法了。扩展方法是C#3.0的新增特性,这也是上述例子迈向LINQ 的第一个变化。下面我们就来介绍一下扩展方法。

二。扩展方法

 请看下面关于扩展方法的例子

public static class helper

    {

        public static string MD5Hash(this string s)

        {

            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(s, "MD5");

        }

        public static bool In(this object o, IEnumerable b)

        {

            foreach (object obj in b)

            {

                if (obj == o)

                    return true;

            }

            return false;

        }

    }

    // 调用扩展方法

    Response.Write("123456".MD5Hash());

    Response.Write("1".In(new[]{"1","2","3"}));

上面的例子是对string进行了扩展,这样的话只要在当前命名空间下任何string对象都可以利用该扩展方法。这样会给代码带来很大的方便。

既然有了扩展方法,我们的Linq自然就很容易就出现了。就如同下面的Linq例子一样

          MethodInfo[] methods = typeof(string).GetMethods();

            var result = from m in methods

                         where m.IsStatic != true

                         select m.Name;

            foreach (var r in result)

            {

                Response.Write(r.ToString()+"<br/>");

            }

这就是Linq最典型的样子。是不是比较像我们平时用的SQL呢?呵呵虽然还有不小的差别,但是Linq的引入实在是C#的一种革命性的变化。他不仅好用,更给枯燥的C#代码注入了一股鲜活的思想。

三。λ表达式

 C# 3.0 给匿名方法提供了一个新的语法——λ表达式(也叫做Lambda表达式)。除了把匿名方法传送给Where()、OrderbyDescen
ding()和Select()方法之外,还可以使用λ表达式。
λ 表达式参见第7 章。λ表达式在LINQ 中非常重要,所以下面复习一下该语法。详细信息可参见第7
章。
比较λ表达式和匿名委托,会发现许多类似之处。λ运算符=>的左边是参数,不需要添加参数类型,因
为它们是由编译器解析的。λ运算符的右边定义了执行代码。在匿名方法中,需要花括号和return 语句。在
λ表达式中,不需要这些语法元素,因为它们是由编译器处理的。如果λ运算符右边有多个语句,也可以使
用花括号和return 语句。
例如下面的例子

  var list = new[] { "aa", "bb", "ca" };

  var resultList = Array.FindAll(list, s => (s.IndexOf("a") > -1));

  foreach (var v in resultList)

      Response.Write(v+"<br/>");

s就像是我们在第一个例子中使用的delegate(string s)里面的s一样只是这种使用方法更加的灵活和方便。

四。LINQ 查询

我们就以NorthWind数据库为例,添加一个Linq to Sql Classes命名为Customer.dbml,然后打开Server Explorer设置好连接参数,选择Customers表直接拖拽到Customer.dbml,打开Customer.design.cs文件我们可以看到Visual Studio为我们生成了很多代码。这些代码我们会在后面的内容里详细的讲解。现在主要来讲一下Linq查询以及后面的内容。

LINQ 查询是C#语言中的一个简化查询记号。编译器编译查询表达式,调用扩展方法。查询表达式只是C#中的一个语法,但不需要修改底层的IL 代码。查询表达式必须以from子句开头,以select或group子句结束。在这两个子句之间,可以使用where、orderby、join、let 和其他from子句。注意,变量query只指定了LINQ查询。该查询不是通过这个赋值语句执行的,只要使用foreach循环访问查询,该查询就会执行。

推迟查询的执行

在运行期间定义查询表达式时,查询就不会运行。查询会在迭代数据项时运行。再看看扩展方法Where()。它使用yield return语句返回谓词为true的元素。因为使用了yield return语句,所以编译器会创建一个枚举器,在访问枚举中的项后,就返回它们。

        public static IEnumerable<T> Where<T>(this IEnumerable<T> source,Func<T, bool> predicate)

        {

            foreach (T item in source)

                if (predicate(item))

                    yield return item;

        }

请看一下下面的代码

var names = new List<string>{"Nino","Alberto", "Juan", "Mike", "Phil"};
            var namesWirhJ = (from name in names where name.StartsWith("J") orderby name select name);
            Response.Write("First Iteration<br/>");
            foreach (var name in namesWirhJ)
                Response.Write(name + "<br/>");
            names.Add("John");
            names.Add("Jim");
            names.Add("Jack");
            names.Add("Denny");
            Response.Write("Second iteration<br/>");
            foreach (var name in namesWirhJ)
                Response.Write(name + "<br/>");

其返回结果为

First iteration
Juan
Second iteration
Jack
Jim
John
Juan

但是当我们修改一下代码将 var namesWirhJ = (from name in names where name.StartsWith("J") orderby name select name);换做var namesWirhJ = (from name in names where name.StartsWith("J") orderby name select name).ToList();那么结果就成了

First iteration
Juan
Second iteration
Juan

这就是我们需要注意的地方了,每次在迭代中使用查询时,都会调用扩展方法。在大多数情况下,这是非常有效的,因为我们可以检测出源数据中的变化。但是在一些情况下,这是不可行的。调用扩展方法ToArray()、ToEnu
merable()、ToList()等可以改变这个操作。这也就是为什么我们需要演示ToList()方法了。ToList 迭代集合,返回一个实现了List<string>的集合。之后对返回的列表迭代两次,在这个过程中,数据源被修改了,但是原来的集合并没有改变。这样可以用来实现一些比较复杂的业务逻辑。

五。标准查询操作符

Where、OrderByDescending 和Select 只是LINQ 的几个查询操作符。LINQ 查询为最常用的操作符定
义了一个声明语法。还有许多标准查询操作符。下表列出了Linq的标准查询操作符。

 

Where

OfType<TResult>

过滤操作符定义了返回元素的条件。在Where 查询操作符中,可以使用谓词,

例如λ表达式定义的谓词,来返回布尔值。OfType<TResult>根据类型过滤元素,只

返回TResult 类型的元素

Select和SelectMany

投射操作符用于把对象转换为另一个类型的对象。Select 和SelectMany 定义

了根据选择器函数选择结果值的投射

OrderBy,ThenBy

OrderByDescending

ThenByDescending

Reverse

排序操作符改变所返回的元素的顺序。OrderBy 按升序排序,

OrderByDescending 按降序排序。如果第一次排序的结果很类似,就可以使用

ThenBy 和ThenBy Descending 操作符进行第二次排序。Reverse 反转集合中元

素的顺序

Join,GroupJoin

连接运算符用于合并不直接相关的集合。使用Join 操作符,可以根据键选择

器函数连接两个集合,这类似于SQL 中的JOIN。GroupJoin 操作符连接两个集

合,组合其结果

GroupBy

组合运算符把数据放在组中。GroupBy 操作符组合有公共键的元素

Any,All,Contains

如果元素序列满足指定的条件,量词操作符就返回布尔值。Any,All 和Contains

都是量词操作符。Any 确定集合中是否有满足谓词函数的元素;All 确定集合

中的所有元素是否都满足谓词函数;Contains 检查某个元素是否在集合中。这些操作

符都返回一个布尔值

Take,Skip,

TakeWhile

SkipWhile

分区操作符返回集合的一个子集。Take、Skip、TakeWhile 和SkipWhile 都是

分区操作符。使用它们可以得到部分结果。使用Take 必须指定要从集合中提

取的元素个数;Skip 跳过指定的元素个数,提取其他元素,TakeWhile 提取条件为真的

元素

Distinct,Union

Intersect,Except

Set 操作符返回一个集合。Distinct 从集合中删除重复的元素。除了Distinct

之外,其他Set 操作符都需要两个集合。Union 返回出现在其中一个集合中的

元素。Intersect 返回两个集合中都有的元素。Except 返回只出现在一个集合

中的元素

First

FirstOrDefault

Last

LastOrDefault

ElementAt

ElementAtOrDefault

Single

SingleOrDefault

这些元素操作符仅返回一个元素。First 返回第一个满足条件的元素。

FirstOrDefault 类似于First,但如果没有找到满足条件的元素,就返回类型

的默认值。Last 返回最后一个满足条件的元素。ElementAt 指定了要返回的元

素的位置。Single 只返回一个满足条件的元素。如果有多个元素都满足条件,

就抛出一个异常

Count,Sum,Min,

Max,Average,

Aggregate

合计操作符计算集合的一个值。利用这些合计操作符,可以计算所有值的总和、

元素的个数、值最大和最小的元素,平均值等

ToArray

ToEnumerable

ToList

ToDictionary

toType<T>

这些转换操作符将集合转换为数组、IEnumerable、IList、IDictionary 等

Empty,Range,

Repeat

这些生成操作符返回一个新集合。使用Empty,集合是空的,Range 返回一系列数

字,Repeat 返回一个始终重复一个值的集合

注:本文内容摘自http://blog.sina.com.cn/s/blog_5df2629a0100lr3u.html

 

ASP.NET开发技术交流群: 67511751(人员招募中...)

posted on 2011-08-31 16:02  Juvy  阅读(401)  评论(0编辑  收藏  举报
QQ:1054930154; Email:david.telvent@gmail.com; QQ群:67511751