C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#中Linq的基础操作

C#中Linq的入门教程

作者:springsnow

这篇文章介绍了C#中Linq的基础操作,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、LINQ的体系结构

语言集成查询 (LINQ) (C#) | Microsoft 官方文档

LINQ总共包括五个部分:

 

程序集

命名空间

描述

LINQ to Objects

System.Core.dll

System.Linq

提供对内存中集合操作的支持

LINQ to XML

System.Xml.Linq.dll

System.Xml.Linq

提供对XML数据源的操作的支持

LINQ to SQL

System.Data.Linq.dll

System.Data.Linq

提供对Sql Server数据源操作的支持。(微软已宣布不再更新,推荐使用LINQ to Entities)

LINQ to DataSet

System.Data.DataSetExtensions.dll

System.Data

提供对离线数据集DataTable操作的支持。

LINQ to Entities

System.Core.dll 和System.Data.Entity.dll

System.Linq和System.Data.Objects

LINQ to Entities 是 Entity Framework 的一部分并且取代LINQ to SQL 作为在数据库上使用 LINQ 的标准机制。

目前,除了以下的,还可以下载其他第三方提供程序,例如LINQ to JSON、LINQ to MySQL、LINQ to Amazon、LINQ to Flickr和LINQ to SharePoint。无论使用什么数据源,都可以通过LINQ使用相同的API进行操作。

二、 LINQ的语法

1、Query查询表达式语法

LINQ查询表达式以from子句开头,以select子句或group子句结束。

在两个子句之间,可以使用where、orderby、join、let等查询操作符。

关键字有: from 、where 、select 、group 、into 、orderby、join、let、in、on、equals、by、ascending、descending等。

编译器会在程序编译时转换LINQ查询,以调用相应的扩展方法。

下面是一个简单的示例,查询一个int数组中小于5的元素,并按照从小到大的顺序排列:

int[] arr = new int[] { 1, 4, 2, 6, 7, 9, 5, 1, 2, 4 };
var query = from r in arr
            where r < 5
            orderby r
            select r;
foreach (var item in query)
{
    Console.WriteLine(item);
}
Console.ReadLine();

Linq语句最终被转换为调用IEnumerable<T>的扩展方法,在System.Linq.Enumerable静态类中定义了N多扩展。所以只要继承与IEnumerable的类都支持Linq查询 。

2、Lambda语法

标准查询操作符

Enumberable 类定义的标准查询操作符。

3、扩展方法存在对应的查询表达式关键字:

三、LINQ的特性

1、延迟执行查询

LINQ具有“延迟计算”的特性。

Linq的执行不是在Linq的赋值语句执行,而是在通过foreach遍历访问结果时执行。

var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" };

var namesWithJ = (from n in names
                  where n.StartsWith("J")
                  orderby n
                  select n);

Console.WriteLine("First iteration");
foreach (string name in namesWithJ)
{
    Console.WriteLine(name);
}
Console.WriteLine();

names.Add("John");
names.Add("Jim");
names.Add("Jack");
names.Add("Denny");

Console.WriteLine("Second iteration");
foreach (string name in namesWithJ)
{
    Console.WriteLine(name);
}

返回的结果是:

两次遍历的结果不一样,说明执行并不是在Linq的定义语句执行,而是在foreach执行。

换成如下,两次执行结果就一样了。

var namesWithJ = (from n in names
                  where n.StartsWith("J")
                  orderby n
                  select n
).ToList();

2、运算符延迟计算符号

按字母顺序整理:

1、具有延迟计算的运算符

Cast,Concat,DefaultIfEmpty,Distinct,Except,GroupBy,GroupJoin,Intersect,Join,OfType,OrderBy,OrderByDescending,Repeat,Reverse,Select,SelectMany,Skip,SkipWhile,Take,TakeWhile,ThenBy,ThenByDescending,Union,Where,Zip

2、立即执行的运算符

对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。CountMaxAverage 和 First 就属于此类查询。

由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句,直接立即执行。

Aggregate,All,Any,Average,Contains,Count,ElementAt,ElementAtOrDefault,Empty,First,FirstOrDefault,Last,LastOrDefault,LongCount,Max,Min,Range,SequenceEqual,Single,SingleOrDefault,Sum,ToArray,ToDictionary,ToList,ToLookup

注意:特殊的AsEnumerable运算符,用于处理LINQ to Entities操作远程数据源,将IQueryable远程数据立即转化为本地的IEnumerable集合。若AsEnumerable接收参数是IEnumerable内存集合则什么都不做。

3、强制立即执行

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

通过调用 ToList 或 ToArray,可以将所有数据缓存在单个集合对象中。

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

四、使用 LINQ 进行数据转换

语言集成查询 (LINQ) 不仅可用于检索数据,而且还是一个功能强大的数据转换工具。

通过使用 LINQ 查询,您可以将源序列用作输入,并采用多种方式修改它以创建新的输出序列。您可以通过排序和分组来修改该序列,而不必修改元素本身。

但是,LINQ 查询的最强大的功能是能够创建新类型。这一功能在 select 子句中实现。

例如,可以执行下列任务:

1、将多个输入联接到一个输出序列

class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
    public List<int> Scores { get; set; }
}

class Teacher
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
}

private static void Main(string[] args)
{
    //创建第一个数据源
    var students = new List<Student>() {
            new Student () {
            Age = 23,
            City = "广州",
            Name = "小C",
            Scores = new List<int> () { 85, 88, 83, 97 }
            },
            new Student () {
            Age = 18,
            City = "广西",
            Name = "小明",
            Scores = new List<int> () { 86, 78, 85, 90 }
            },
            new Student () {
            Age = 33,
            City = "梦里",
            Name = "小叁",
            Scores = new List<int> () { 86, 68, 73, 97 }
            }
        };

    //创建第二个数据源
    var teachers = new List<Teacher>() {
            new Teacher () {
            Age = 35,
            City = "梦里",
            Name = "啵哆"
            },
            new Teacher () {
            Age = 28,
            City = "云南",
            Name = "小红"
            },
            new Teacher () {
            Age = 38,
            City = "河南",
            Name = "丽丽"
            }
        };

    //创建查询
    var peopleInDreams = (from student in students
                          where student.City == "梦里"
                          select student.Name)
                .Concat(from teacher in teachers
                        where teacher.City == "梦里"
                        select teacher.Name);

    //执行查询
    foreach (var person in peopleInDreams)
    {
        Console.WriteLine(person);
    }

    Console.Read();
}

结果

小叁 
啵哆

2、选择各个源元素的子集

1. 若要只选择源元素的一个成员,请使用点运算。

var query = from cust in Customers
               select cust.City;

2. 若要创建包含源元素的多个属性的元素,可以使用具有命名对象或匿名类型的对象初始值设定项。

var query = from cust in Customer
               select new {Name = cust.Name, City = cust.City};

3、将内存中的对象转换为 XML

//创建数据源
var students = new List<Student>()
            {
                new Student()
                {
                    Age = 18,
                    Name = "小A",
                    Scores = new List<int>() {88,85,74,66 }
                },
                new Student()
                {
                    Age = 35,
                    Name = "小B",
                    Scores = new List<int>() {88,85,74,66 }
                },
                new Student()
                {
                    Age = 28,
                    Name = "小啥",
                    Scores = new List<int>() {88,85,74,66 }
                }
            };

//创建查询
var studentsToXml = new XElement("Root",
    from student in students
    let x = $"{student.Scores[0]},{student.Scores[1]},{student.Scores[2]},{student.Scores[3]}"
    select new XElement("student",
           new XElement("Name", student.Name),
           new XElement("Age", student.Age),
           new XElement("Scores", x))
);

//执行查询
Console.WriteLine(studentsToXml);

4、 对源元素执行操作

输出序列可能不包含源序列的任何元素或元素属性。

输出可能是通过将源元素用作输入参数计算出的值的序列。

//数据源
double[] radii = { 1, 2, 3 };

//创建查询
var query = from radius in radii
            select $"{radius * radius * 3.14}";

//执行查询
foreach (var i in query)
{
    Console.WriteLine(i);
}

到此这篇关于C#中Linq用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文