加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

LINQ-查询表达式基础

发布时间:2020-12-16 23:37:36 所属栏目:百科 来源:网络整理
导读:一、LINQ查询的数据源 从应用程序的角度来看,原始源数据的特定类型和结构并不重要。? 应用程序始终将源数据视为?IEnumerableT?或?IQueryableT?集合。? 例如在 LINQ to XML 中,源数据显示为? IEnumerable XElement。所以要对某个对象应用LINQ查询,该对象必

一、LINQ查询的数据源

  从应用程序的角度来看,原始源数据的特定类型和结构并不重要。?应用程序始终将源数据视为?IEnumerable<T>?或?IQueryable<T>?集合。?

例如在 LINQ to XML 中,源数据显示为?IEnumerable<XElement>。所以要对某个对象应用LINQ查询,该对象必须实现?IEnumerable<T>?或?IQueryable<T>?。

  其中,数组类型并为实现?IEnumerable<T>?或?IQueryable<T>?,为什么也可进行LINQ查询呢?

二、查询可能会执行三种操作

  • 检索元素的子集以生成新序列,而不修改各个元素。?查询然后可能以各种方式对返回的序列进行排序或分组,如下面的示例所示(假定?scores?是?int[]):

IEnumerable<int> highScoresQuery = from score in scores where score > 80 orderby score descending select score;

  • 如前面的示例所示检索元素的序列,但是将它们转换为新类型的对象。?例如,查询可以只从数据源中的某些客户记录检索姓氏。或者可以检索完整记录,然后用于构造其他内存中对象类型甚至是 XML 数据,再生成最终的结果序列。?下面的示例演示从?int到?string?的投影。?请注意?highScoresQuery?的新类型。

?

IEnumerable<string> highScoresQuery2 =
    from score in scores
    where score > 80
    orderby score descending
    select $"The score is {score}";
  • 检索有关源数据的单独值,如:

?

    • 与特定条件匹配的元素数。

    • 具有最大或最小值的元素。

    • 与某个条件匹配的第一个元素,或指定元素集中特定值的总和。?例如,下面的查询从?scores?整数数组返回大于 80 的分数的数量:

int highScoreCount =
    (from score in scores
     where score > 80
     select score)
     .Count();

在前面的示例中,请注意在调用?Count?方法之前,在查询表达式两边使用了括号。?也可以通过使用新变量存储具体结果,来表示此行为。?这种方法更具可读性,因为它使存储查询的变量与存储结果的查询分开。

IEnumerable<int> highScoresQuery3 =
    from score in scores
    where score > 80
    select score;

int scoreCount = highScoresQuery3.Count();

三、查询表达式

查询表达式必须以?from?子句开头,且必须以?select?或?group?子句结尾。在第一个?from?子句与最后一个?select?或?group?子句之间,可以包含以下这些可选子句中的一个或多个:where、orderby、join、let,甚至是其他?from?子句。?还可以使用?into?关键字,使?join?或?group?子句的结果可以充当相同查询表达式中的其他查询子句的源。

下面的代码示例演示一个简单查询表达式,它具有一个数据源、一个筛选子句、一个排序子句并且不转换源元素。?该查询以?select子句结尾。

?

static void Main()
{
    // Data source.
    int[] scores = { 90,71,82,93,75,82 };

    // Query Expression.
    IEnumerable<int> scoreQuery = //query variable
        from score in scores //required
        where score > 80 // optional
        orderby score descending // optional
        select score; //must end with select or group

    // Execute the query to produce the results
    foreach (int testScore in scoreQuery)
    {
        Console.WriteLine(testScore);
    }                  
}
// Outputs: 93 90 82 82

查询变量

在上面的示例中,scoreQuery?是查询变量,它有时仅仅称为查询。查询变量可以存储采用查询语法、方法语法或是两者的组合进行表示的查询,而不是查询的结果。

开始查询表达式

查询表达式必须以?from?子句开头。?它指定数据源以及范围变量。?范围变量表示遍历源序列时,源序列中的每个连续元素。?范围变量基于数据源中元素的类型进行强类型化。?在下面的示例中,因为?countries?是?Country?对象的数组,所以范围变量也类型化为?Country。?因为范围变量是强类型,所以可以使用点运算符访问该类型的任何可用成员。

IEnumerable<Country> countryAreaQuery =
    from country in countries
    where country.Area > 500000 //sq km
    select country;

范围变量一直处于范围中,直到查询使用分号或 continuation 子句退出。

查询表达式可能会包含多个?from?子句。?在源序列中的每个元素本身是集合或包含集合时,可使用其他?from?子句。?例如,假设具有?Country?对象的集合,其中每个对象都包含名为?Cities?的?City?对象集合。?若要查询每个?Country?中的?City?对象,请使用两个?from?子句,如下所示:

IEnumerable<City> cityQuery =
    from country in countries
    from city in country.Cities
    where city.Population > 10000
    select city;

结束查询表达式

查询表达式必须以?group?子句或?select?子句结尾。

group 子句

使用?group?子句可生成按指定键组织的组的序列。?键可以是任何数据类型。?例如,下面的查询会创建包含一个或多个?Country?对象并且其键是?char?值的组的序列。

?

var queryCountryGroups =
    from country in countries
    group country by country.Name[0];

select 子句

使用?select?子句可生成所有其他类型的序列。?简单?select?子句只生成类型与数据源中包含的对象相同的对象的序列。?在此示例中,数据源包含?Country?对象。?orderby?子句只按新顺序对元素进行排序,而?select?子句生成重新排序的?Country?对象的序列。

?

IEnumerable<Country> sortedQuery =
    from country in countries
    orderby country.Area
    select country;

select?子句可以用于将源数据转换为新类型的序列。?此转换也称为投影。?在下面的示例中,select?子句对只包含原始元素中的字段子集的匿名类型序列进行投影。?请注意,新对象使用对象初始值设定项进行初始化。

// Here var is required because the query
// produces an anonymous type.
var queryNameAndPop =
    from country in countries
    select new { Name = country.Name,Pop = country.Population };

使用“into”进行延续

可以在?select?或?group?子句中使用?into?关键字创建存储查询的临时标识符。?如果在分组或选择操作之后必须对查询执行其他查询操作,则可以这样做。?在下面的示例中,countries?按 1000 万范围,根据人口进行分组。?创建这些组之后,附加子句会筛选出一些组,然后按升序对组进行排序。?若要执行这些附加操作,需要由?countryGroup?表示的延续。

?

// percentileQuery is an IEnumerable<IGrouping<int,Country>>
var percentileQuery =
    from country in countries
    let percentile = (int) country.Population / 10_000_000
    group country by percentile into countryGroup
    where countryGroup.Key >= 20
    orderby countryGroup.Key
    select countryGroup;

// grouping is an IGrouping<int,Country>
foreach (var grouping in percentileQuery)
{
    Console.WriteLine(grouping.Key);
    foreach (var country in grouping)
        Console.WriteLine(country.Name + ":" + country.Population);
}

筛选、排序和联接

在开头?from?子句与结尾?select?或?group?子句之间,所有其他子句(wherejoinorderbyfromlet)都是可选的。任何可选子句都可以在查询正文中使用零次或多次。

?

where 子句

?使用?where?子句可基于一个或多个谓词表达式,从源数据中筛选出元素。?以下示例中的?where?子句具有一个谓词及两个条件。

IEnumerable<City> queryCityPop =
    from city in cities
    where city.Population < 200000 && city.Population > 100000
    select city;

orderby 子句

使用?orderby?子句可按升序或降序对结果进行排序。?还可以指定次要排序顺序。?下面的示例使用?Area?属性对?country?对象执行主要排序。?然后使用?Population?属性执行次要排序。

?

IEnumerable<Country> querySortedCountries =
    from country in countries
    orderby country.Area,country.Population descending
    select country;

ascending?关键字是可选的;如果未指定任何顺序,则它是默认排序顺序。?

join 子句

使用?join?子句可基于每个元素中指定的键之间的相等比较,将一个数据源中的元素与另一个数据源中的元素进行关联和/或合并。在 LINQ 中,联接操作是对元素属于不同类型的对象序列执行。?联接了两个序列之后,必须使用?select?或?group?语句指定要存储在输出序列中的元素。?还可以使用匿名类型将每组关联元素中的属性合并到输出序列的新类型中。?下面的示例关联其?Category?属性与?categories?字符串数组中一个类别匹配的?prod?对象。?筛选出其?Category?不与?categories?中的任何字符串匹配的产品。select?语句会投影其属性取自?cat?和?prod?的新类型。

?

var categoryQuery =
    from cat in categories
    join prod in products on cat equals prod.Category
    select new { Category = cat,Name = prod.Name };

还可以通过使用?into?关键字将?join?操作的结果存储到临时变量中来执行分组联接。

let 子句

?使用?let?子句可将表达式(如方法调用)的结果存储在新范围变量中。?在下面的示例中,范围变量?firstName?存储?Split?返回的字符串数组的第一个元素。

string[] names = { "Svetlana Omelchenko","Claire O‘Donnell","Sven Mortensen","Cesar Garcia" };
IEnumerable<string> queryFirstNames =
    from name in names
    let firstName = name.Split( )[0]
    select firstName;

foreach (string s in queryFirstNames)
    Console.Write(s + " ");
//Output: Svetlana Claire Sven Cesar

查询表达式中的子查询

查询子句本身可能包含查询表达式,这有时称为子查询。?每个子查询都以自己的?from?子句开头,该子句不一定指向第一个?from子句中的相同数据源。?例如,下面的查询演示在 select 语句用于检索分组操作结果的查询表达式。

?

var queryGroupMax =
    from student in students
    group student by student.GradeLevel into studentGroup
    select new
    {
        Level = studentGroup.Key,HighestScore =
            (from student2 in studentGroup
             select student2.Scores.Average())
             .Max()
    };

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读