C# 学习笔记(14)—— LINQ

2023-10-20 18:51:43 浏览数 (2)

LINQ 是什么

LINQ 是 Lanuage Integrated Query 的缩写,即“语言集成查询”的意思。众所周知,做软件开发离不开数据的,你肯定听过SQL数据库、Oracle数据库或本地XML文档等。每种数据源都有自己的查询语言,例如SQL数据库有自己的SQL语言,。LINQ的提出就是为了提供一种跨越各种数据源的统一的查询方式,它主要包括四个组件——Linq to Objects、Linq to XML、Linq to DataSet 和 Linq to SQL

简单介绍一下LINQ的四个组件

  • Linq to SQL 组件。它可以查询关系数据库的数据。微软只实现了对 SQL Server 数据库的查询,包括对其中数据进行查询、修改和删除等操作。而众多开发者、爱好者则根据各自需求实现针对其他数据库的相关扩展
  • Linq to DataSet 组件。它可以查询 DataSet 对象中的数据,并能对数据进行增删改查等操作
  • Linq to XML 组件。该组件可以查询 XML 文件,在它被提出之前,C# 中使用 XPath 来对 XML 进行查询,但该工具没有 Linq to XML 更加简洁
  • Linq to Objects 组件。这个组件可以查询集合数据,如数组或List等

LINQ 好在哪里

LINQ 的四个组件分别实现了对不同的数据类型进行增、删、改、查等操作,在 LINQ 提出之前,C# 也是有相关技术 完成这些操作的。例如对于数据库,之前就有 ADO.NET;而对于 XML,之前则有 XPath,那我们为什么还需要 LINQ 呢?

原因在于,LINQ 使对这些数据源进行的操作变得更加简单、方便和易于理解。之前的技术过于繁琐,在“希望可以做得更好”的“上进心”的驱动下,微软在 C# 3.0 中提出了 LINQ。下面通过对比的方式来展示 LINQ 技术的简洁性

查询表达式

在说明 LINQ 的好处之前,你需要首先了解“查询表达式”。查询表达式必须以 from 子句开头,并且必须以 select 或 group 子句结尾,在第一个 from 子句和最后一个 select 或 group 子句之间,可以包含一个或多个 where 子句、orderby、join子句。其形式非常类似于 SQL 语言,只是书写形式颠倒了过来。下面给出一个简单的表达式:

代码语言:javascript复制
// 查询表达式
var queryExp = from s in collection
                          select s;
// 点标记法
var queryExp = collection.select(s => s);

点标记法适合查询条件较少的情况,而查询表达式则更加组中结构化思维方式,类似于 SQL 语法

使用 LINQ to Objects 查询集合

在 LINQ 提出之前,我们查询集合中的数据一般都是使用 for 和 foreach 语句,但这种方式没有 Linq to Objects 来得简介,且不容易添加筛选条件。下面假设一个场景来比较这两种技术——返回集合中是偶数的序列

使用 foreach 语句来返回集合中偶数序列的实现代码如下:

代码语言:javascript复制
using System;
using System.Collections.Generic;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<int>();
            for (int i = 0; i < 10; i  )
            {
                list.Add(i);
            }
            OldQuery(list);
            Console.ReadKey();
        }

        private static void OldQuery(List<int> collection)
        {
            foreach (var item in collection)
            {
                if (item % 2 == 0)
                {
                    Console.WriteLine(item);
                }
            }
        }
    }
}

我们在看看 LINQ 来实现同样功能的代码:

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<int>();
            for (int i = 0; i < 10; i  )
            {
                list.Add(i);
            }
            OldQuery(list);
            Console.ReadKey();
        }

        private static void OldQuery(List<int> collection)
        {
            var queryResults = from item in collection
                               where item % 2 == 0
                               select item;

            foreach (var item in queryResults)
            {
                Console.WriteLine(item);
            }
        }
    }
}

从以上代码来看,使用 Linq to Objects 来查询集合对象,代码更加简洁了。而且 LINQ 还方便添加筛选条件,只需要在 where 子句中添加即可;在原来的方式中,添加筛选条件就没那么简洁,需要多写几个 if 语句。通过对比,可以看出 Linq to Objects 在查询集合对象时的优势,所以对于 C# 3.0 之后的代码,建议你都是用 Linq to Objects 来实现对集合对象的查询、修改等操作

使用 Linq to XML 查询 XML 文件

在 LINQ 提出之前,我们可以使用 XPath 来查询 XML 文件。但使用 XPath 时必须首先知道 XML 文件的具体结构,而使用 Linq to XML 则不需要知道这些。而且 Linq to XML 的代码还更加简洁,下面同样以对比方式来说明这点

假设有一个一定定义好的 XML 文件,现在需要查询出 XML 文件中 Name 节点为“李四”的元素。首先看使用 XPath 方式实现的代码:

代码语言:javascript复制
using System;
using System.Xml;

namespace Demo
{
    class Program
    {
        private static string xmlString = @"
<Persons>
    <Person>
        <Name>张三</Name>
        <Age>22</Age>
    </Person>
    <Person>
        <Name>李四</Name>
        <Age>21</Age>
    </Person>
</Persons>
";
        static void Main(string[] args)
        {
            OldXmlQuery(xmlString);
            Console.ReadKey();
        }

        private static void OldXmlQuery(string xml)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);

            // 创建查询 XML 的 XPath
            string xPath = "/Persons/Person";

            // 查询 Person 元素
            XmlNodeList xmlNodeList = xmlDocument.SelectNodes(xPath);

            foreach (XmlNode node in xmlNodeList)
            {
                foreach (XmlNode childNode in node)
                {
                    if (childNode.InnerXml == "李四")
                    {
                        Console.WriteLine($"{childNode.InnerXml}");
                    }
                }
            }
        }
    }
}

从以上代码可知,使用 XPath 方式来查询 XML 文件时,需要首先知道 XML 文件的具体结构,这样才能出实话选择路径(如代码中的选择路径就指定为“/Persons/Person”)

使用 Linq to XML 则不需要知道 XML 文档的结构,下面来看 Linq to XML 的实现代码:

代码语言:javascript复制
using System;
using System.Linq;
using System.Xml.Linq;

namespace Demo
{
    class Program
    {
        private static string xmlString = @"
<Persons>
    <Person>
        <Name>张三</Name>
        <Age>22</Age>
    </Person>
    <Person>
        <Name>李四</Name>
        <Age>21</Age>
    </Person>
</Persons>
";
        static void Main(string[] args)
        {
            LinqQuery(xmlString);
            Console.ReadKey();
        }

        private static void LinqQuery(string xml)
        {
            XElement xElement = XElement.Parse(xml);

            var queryResults = from el in xElement.Elements("Person")
                               where el.Element("Name").Value == "李四"
                               select el;

            foreach (var item in queryResults)
            {
                Console.WriteLine(item.Element("Name").Value);
            }
        }
    }
}

从以上代码可以看出,使用 Linq to XML 查询 XML 文件,代码明显简洁很多,只需要一个查询表达式即可,不需要知道并制定选择路径,也不需要过多的 if 条件判断语句,代码看起来更直接

Linq to DataSet 的例子,这里就不再给出了,它的使用方式类似于 Linq to Object,只是 Linq to DataSet 查询的不是集合对象而是 DataSet 对象了

对于 Linq to SQL,这里也不会详细去介绍了,它的内容可以写厚厚一本书了

理解 LINQ 的本质

对于编译器而言,使用 LINQ 查询表达式的代码于使用方法调用的代码完全没有区别

归纳总结

数据查询如果使用 LINQ 的方式去实现,要考虑数据量,避免内存溢出

0 人点赞