LINQ学习系列之LINQ入门

LINQ查询介绍
语言集成查询 (LINQ) 在对象领域和数据领域之间架起了一座桥梁。
LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况。在 LINQ 查询中,始终会用到对象。可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、.NET 集合中的数据以及对其有 LINQ 提供程序可用的任何其他格式的数据。

查询操作的三个部分

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

class IntroToLINQ
{       
    static void Main()
    {
        // The Three Parts of a LINQ Query:
        //  1. Data source.
        int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

        // 2. Query creation.
        // numQuery is an IEnumerable<int>
        var numQuery =
            from num in numbers
            where (num % 2) == 0
            select num;

        // 3. Query execution.
        foreach ( int num in numQuery)
        {
            Console.Write( "{0,1} ", num);
        }
    }
}

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

数据源
LINQ 数据源是支持泛型 IEnumerable < (Of < (T > ) > ) 接口或从该接口继承的接口的任意对象。
支持非泛型 IEnumerable 接口的类型(如 ArrayList)也可用作 LINQ 数据源。
支持 IEnumerable < (Of < (T > ) > ) 或派生接口(如泛型 IQueryable < (Of < (T > ) > ))的类型称为“可查询类型”。

LINQ to XML 将 XML 文档加载到可查询的 XElement 类型中:
// Create a data source from an XML document.
// using System.Xml.Linq;
XElement contacts = XElement.Load(@"c:\myContactList.xml");

LINQ to SQL
// Create a data source from a SQL Server database.
// using System.Data.Linq;
DataContext db = new DataContext(@"c:\northwind\northwnd.mdf");


查询
查询指定要从数据源中检索的信息。查询还可以指定在返回这些信息之前如何对其进行排序、分组和结构化。查询存储在查询变量中,并用查询表达式进行初始化。

from
where
select


查询表达式包含三个子句:fromwhereselect。(如果您熟悉 SQL,您会注意到这些子句的顺序与 SQL 中的顺序相反。) from 子句指定数据源,where 子句应用筛选器,select 子句指定返回的元素的类型。

在 LINQ 中,查询变量本身不执行任何操作并且不返回任何数据。它只是存储在以后某个时刻执行查询时为生成结果而必需的信息。

查询执行
延迟执行
查询变量本身只是存储查询命令,
实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。此概念称为“延迟执行”
//  Query execution. 

foreach (int num in numQuery)

{

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

}
 
强制立即执行

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

var evenNumQuery =
    from num in numbers
    where (num % 2) == 0
    select num;

int evenNumCount = evenNumQuery.Count();
若要强制立即执行任意查询并缓存其结果,可以调用 ToList<(Of <(TSource>)>) 或 ToArray<(Of <(TSource>)>) 方法。
List<int> numQuery2 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToList();

// or like this:
// numQuery3 is still an int[]

var numQuery3 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToArray();
 

LINQ 和泛型类型
1. 当您创建泛型集合类(如 List<(Of <(T>)>))的实例时,您将“T”替换为列表将包含的对象的类型。例如,字符串列表表示为 List<string>Customer 对象列表表示为 List<Customer>。泛型列表是强类型的,且提供了比将其元素存储为 Object 的集合更多的好处。
2. IEnumerable<(Of <(T>)>) 是一个接口,泛型集合类支持 IEnumerable<(Of <(T>)>),就像非泛型集合类(如 ArrayList)支持 IEnumerable。LINQ 查询变量类型化为 IEnumerable<(Of <(T>)>) 或派生类型,如 IQueryable<(Of <(T>)>)。当您看到类型化为 IEnumerable<Customer> 的查询变量时,这只意味着在执行该查询时,该查询将生成包含零个或多个 Customer 对象的序列。

LINQ 查询中的 IEnumerable<T> 变量
LINQ 查询变量类型化为 IEnumerable<(Of <(T>)>) 或派生类型,如 IQueryable<(Of <(T>)>)。当您看到类型化为 IEnumerable<Customer> 的查询变量时,这只意味着在执行该查询时,该查询将生成包含零个或多个 Customer 对象的序列。
IEnumerable<Customer> customerQuery =
    from cust in customers
    where cust.City == "London"
    select cust;

foreach (Customer customer in customerQuery)
{
    Console.WriteLine(customer.LastName + ", " + customer.FirstName);
}
让编译器处理泛型类型声明
如果您愿意,可以使用 var 关键字来避免使用泛型语法。var 关键字指示编译器通过查看在 from 子句中指定的数据源来推断查询变量的类型。下面的示例生成与上一个示例相同的编译代码:
var customerQuery2 =
    from cust in customers
    where cust.City == "London"
    select cust;

foreach(var customer in customerQuery2)
{
    Console.WriteLine(customer.LastName + ", " + customer.FirstName);
}


查询语法与方法语法 (LINQ)
通过使用 C# 3.0 中引入的声明性查询语法,介绍性 LINQ 文档中的多数查询都被编写为查询表达式。但是,.NET 公共语言运行库 (CLR) 本身并不具有查询语法的概念。因此,在编译时,查询表达式会转换为 CLR 确实了解的内容:方法调用。这些方法称为“标准查询运算符”,它们具有如下名称:Where、Select、GroupBy、Join、Max、Average 等。可以通过使用方法语法而非查询语法直接调用这些方法。
通常我们建议使用查询语法,因为它通常更简单、更易读;但是方法语法和查询语法之间并无语义上的区别。此外,一些查询(如检索匹配指定条件的元素数的那些查询或检索具有源序列中的最大值的元素的查询)只能表示为方法调用。System.Linq 命名空间中的标准查询运算符的参考文档通常使用方法语法。因此,即使在开始编写 LINQ 查询时,熟悉如何在查询和查询表达式本身中使用方法语法也非常有用。

Lambda 表达式
在上面的示例中,条件表达式 (num % 2 == 0) 是作为内联参数传递到 Where 方法的:Where(num => num % 2 == 0)。此内联表达式称为 lambda 表达式。
在 C# 中,=> 是 lambda 运算符,可读为“goes to”。

你可能感兴趣的:(LINQ)