LINQ查询入门(一)

来源:互联网 发布:画人体的软件 编辑:程序博客网 时间:2024/05/18 03:27

LINQ查询入门(一)

语言集成查询 (LINQ) 是一组技术的名称,这些技术建立在将查询功能直接集成到 C# 语言(以及 Visual Basic 和可能的任何其他 .NET 语言)的基础上。借助于 LINQ,查询现在已是高级语言构造,就如同类、方法、事件等等。

对于编写查询的开发人员来说,LINQ 最明显的“语言集成”部分是查询表达式。查询表达式是使用 C# 3.0 中引入的声明性查询语法编写的。通过使用查询语法,您甚至可以使用最少的代码对数据源执行复杂的筛选、排序和分组操作。您使用相同的基本查询表达式模式来查询和转换 SQL 数据库、ADO.NET 数据集、XML 文档和流以及 .NET 集合中的数据。

查询是一种从数据源检索数据的表达式。查询通常用专门的查询语言来表示。随着时间的推移,人们已经为各种数据源开发了不同的语言;例如,用于关系数据库的 SQL 和用于 XML XQuery。因此,开发人员不得不针对他们必须支持的每种数据源或数据格式而学习新的查询语言。LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况。在 LINQ 查询中,始终会用到对象。可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、.NET 集合中的数据以及对其有 LINQ 提供程序可用的任何其他格式的数据。

所有 LINQ 查询操作都由以下三个不同的操作组成:

1.    获取数据源。

2.    创建查询。

3.    执行查询。

下面的示例演示如何用源代码表示查询操作的三个部分。为了方便起见,此示例将一个整数数组用作数据源;但其中涉及的概念同样适用于其他数据源。本主题的其余部分也会引用此示例。

C# 

class IntroToLINQ

{       

    static void Main()

    {

        // 通过以下三个步骤建立LINQ查询

        //  1. 数据源.

        int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

 

        // 2. 建立查询.

        // numQuery 是通过 IEnumerable<int>定义的查询

        var numQuery =

            from num in numbers

            where (num % 2) == 0

            select num;

 

        // 3. 执行查询.

        foreach (int num in numQuery)

        {

            Console.Write("{0,1} ", num);

        }

    }

}

 

 

 

下图显示了完整的查询操作。在 LINQ 中,查询的执行与查询本身截然不同;换句话说,如果只是创建查询变量,则不会检索任何数据。

             

数据源

在上一个示例中,由于数据源是数组,因此它隐式支持泛型 IEnumerable<(Of <(T>)>) 接口。这一事实意味着该数据源可以用 LINQ 进行查询。在 foreach 语句中执行查询,而 foreach 要求使用 IEnumerable IEnumerable<(Of <(T>)>)。支持 IEnumerable<(Of <(T>)>) 或派生接口(如泛型 IQueryable<(Of <(T>)>))的类型称为可查询类型

可查询类型不需要进行修改或特殊处理就可以用作 LINQ 数据源。如果源数据还没有作为可查询类型出现在内存中,则 LINQ 提供程序必须以此方式表示源数据。例如,LINQ to XML XML 文档加载到可查询的 XElement 类型中:

C# 

//通过XML文档建立一个数据源.

// 需要调用 using System.Xml.Linq; 包含其命名空间

XElement contacts = XElement.Load(@"c:/myContactList.xml");

LINQ to SQL 中,首先手动或使用 对象关系设计器(O/R 设计器) 在设计时创建对象关系映射。针对这些对象编写查询,然后由 LINQ to SQL 在运行时处理与数据库的通信。在下面的示例中,Customer 表示数据库中的特定表,并且 Table<Customer> 支持派生自 IEnumerable<(Of <(T>)>) 的泛型 IQueryable<(Of <(T>)>) 接口。

C# 

// 通过SQL Server 数据库建立一个数据源.

// 需要调用using System.Data.Linq;包含其命名空间

DataContext db = new DataContext(@"c:/northwind/northwnd.mdf");

 

 

 

查询

查询指定要从数据源中检索的信息。查询还可以指定在返回这些信息之前如何对其进行排序、分组和结构化。查询存储在查询变量中,并用查询表达式进行初始化。为使编写查询的工作变得更加容易,C# 引入了新的查询语法。

上一个示例中的查询从整数数组中返回所有偶数。该查询表达式包含三个子句:fromwhere select。(如果您熟悉 SQL,您会注意到这些子句的顺序与 SQL 中的顺序相反。) from 子句指定数据源,where 子句应用筛选器,select 子句指定返回的元素的类型。LINQ 查询表达式(C# 编程指南)一节中详细讨论了这些子句和其他查询子句。目前需要注意的是,在 LINQ 中,查询变量本身不执行任何操作并且不返回任何数据。它只是存储在以后某个时刻执行查询时为生成结果而必需的信息。 查询

执行

延迟执行

如前所述,查询变量本身只是存储查询命令。实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。此概念称为延迟执行,下面的示例对此进行了演示:

C# 

//  执行查询.

foreach (int num in numQuery)

{

    Console.Write("{0,1} ", num);

}

foreach 语句也是检索查询结果的地方。例如,在上一个查询中,迭代变量 num 保存了返回的序列中的每个值(一次保存一个值)。

由于查询变量本身从不保存查询结果,因此可以根据需要随意执行查询。例如,可以通过一个单独的应用程序持续更新数据库。在应用程序中,可以创建一个检索最新数据的查询,并可以按某一时间间隔反复执行该查询以便每次检索不同的结果。

强制立即执行

对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。CountMaxAverage First 就属于此类查询。由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句。另外还要注意,这些类型的查询返回单个值,而不是 IEnumerable 集合。下面的查询返回源数组中偶数的计数:

C# 

var evenNumQuery =

    from num in numbers

    where (num % 2) == 0

    select num;

 

int evenNumCount = evenNumQuery.Count(); //强制立即执行

 

若要强制立即执行任意查询并缓存其结果,可以调用 ToList<(Of <(TSource>)>) ToArray<(Of <(TSource>)>) 方法。

C# 

List<int> numQuery2 =

    (from num in numbers

     where (num % 2) == 0

     select num).ToList();  //强制立即执行并将其结果保存到numQuery2

 

// 或者可以这样:

// numQuery3 is still an int[]

此外,还可以通过在紧跟查询表达式之后的位置放置一个 foreach 循环来强制执行查询。但是,通过调用 ToList ToArray,也可以将所有数据缓存在单个集合对象中。

 

 
原创粉丝点击