• 咸蛋超人   2014/7/31 12:44:00
  • Linq原理及架构分析
  • 关键字: Linq Linq to sql
  • 基本介绍:

    语言集成查询(LINQ,Language INtegrated Query)是Visual Studio 2008 和 .NET Framework 3.5 版中引入的一项创新功能,它在对象领域和数据领域之间架起了一座桥梁。至今,LINQ仍然得到支持。

    那么LINQ究竟是什么?为什么要引入这项技术?

    在开发中,我们会涉及不同的数据源,例如 XML 文档、SQL 数据库、ADO.NET 数据集、 支持 IEnumerable 或泛型 IEnumerable<T> 接口的任意对象集合中的数据以及对其有 LINQ 提供程序可用的任何其他格式的数据,想要从不同的数据源中获取数据,我们可能需要学习不同的操作方式。于是LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况,我们可以使用相同的基本编码模式(即LINQ语法)来对数据进行查询和操作。

    LINQ的核心是查询表达式。查询是一种从数据源检索数据的表达式。 查询通常用专门的查询语言来表示。

    在.net Framework 3.5中,LINQ分5个功能:

    (1)LINQ To Objects (对对象)

    (2)LINQ To DataSet (对数据集) 

    (3)LINQ To SQL (对Sql数据库)

    (4)LINQ To Entities (对实体)

    (5)LINQ To XML (对XML)

    我们来总体看看LINQ架构:

    LINQ 查询操作

    所有 LINQ 查询操作都由以下三个不同的操作组成:获取数据源、创建查询、执行查询。

    我们先来个例子做对比:查询数组中大于2的并且从小到大排序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    static void Main(string[] args)
        {
           int[] numbers = new int[] { 1, 5, 3, 6, 2};
           List<int> list = new List<int> { };
           foreach (int num in numbers)
                {
                    //大于2的数
                    if (num > 2)
                    {
                        list.Add(num);
                    }
                }
                //list排序
                list.Sort();
                Console.Write("数组中大于2并且从小到大排序:");
                foreach (int ordernum in list)
                {
                    Console.Write("{0} ",ordernum);
                }
           Console.ReadKey();
     }

    看上去是不是比较繁琐呢,使用LINQ可以简化操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    static void Main(string[] args)
      {
         //数据源
         int[] numbers = new int[] { 1, 5, 3, 6, 2};
         //创建查询
         var query = from num in numbers
                            where num > 2
                            orderby num ascending
                            select num;
         Console.Write("数组中大于2并且从小到大排序:");
         //执行查询
                foreach (int num in query)
                {
                    Console.Write("{0} ", num);
                }          
        Console.ReadKey();
    }


    下图显示了完整的查询操作。 在 LINQ 中,当我们创建查询表达式时是不会对数据进行查询的,只有查询执行才去检索数据。换句话说,如果只是创建查询变量,则不会检索任何数据。

    完整LINQ查询操作

    那么对程序进行断点时,会发现foreach会跳转到查询表达式中,然后再检索数据,这就是延迟执行。

    具体理解:

    数据源:LINQ 数据源是支持泛型 IEnumerable<T> 接口或从该接口继承的接口的任意对象。

    创建查询:查询存储在查询变量中,并用查询表达式进行初始化。具体使用的是LINQ 查询语法与方法语法 (C#)。

    执行查询:可分为延迟执行和强制立即执行。

    (1)延迟执行:查询变量本身只是存储查询命令。 实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。 例子如上。

    (2)强制立即执行:对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。 Count、Max、Average 和 First 就属于此类查询。 由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句。 另外还要注意,这些类型的查询返回单个值,而不是 IEnumerable 集合。例子:统计数组中大于2的个数。
    1
    2
    3
    4
    5
    6
    7
    int[] numbers = new int[] { 1, 5, 3, 6, 2};
    int query = (from num in numbers
                            where num > 2
                            select num).Count();
    Console.Write("数组中大于2的个数:{0}个", query);
    Console.ReadKey();
    //返回大于2的个数