详解LINQ入门(下篇)

 更新时间:2020年6月25日 10:35  点击:2018

前 言

终于来到下篇了,通过上篇,和中篇,我们了解了linq的基本语句,对应linq我们又了解到lambda表达式,静态扩展方法,以及linq的延迟加载的特性,那么在本篇文章中我们将分享学习一下linq对于我们开发中常用到的对象的操作应用。如果没有阅读过上篇的请点击这里,如果没有阅读中篇的请点击这里

linq to DataSet

对于做.net 开发的有谁不知道DataSet,DataTable,DataRow,DataColumn这些对象,如果你真的不知道,那好吧建议你到菜市场买2块豆腐撞死算了>_<。也许你会惊讶,哇靠!linq能操作这些?答案是肯定的。那么我们来看看linq是怎么操作的。

1. 命名空间,如果需要linq操作DataSet,需要以下命名空间

using System.Data;
using System.Linq;

2. 关键方法 AsEnumerable,该方法为一个静态扩展方法,他将DataTable转换为一个IEnumerable<DataRow>的序列

var dt = new DataTable();
dt.Columns.Add("A", typeof(int));

var newRow1 = dt.NewRow();
var newRow2 = dt.NewRow();

newRow1["A"] = 1;
newRow2["A"] = 2;

dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);

// 重点看这里
IEnumerable<DataRow> rows = dt.AsEnumerbale();

foreach(row in rows)
  Console.WriteLine(row["A"].ToString());

从这段代码看,并没有什么实质意义,如果这样去遍历datarow就是脱裤子放屁,多此一举。但是这样做的目只有一个为下面的linq操作做铺垫。

3. linq 对 DataRow 操作,以下举例一些linq特有的常用datarow操作

Distinct,顾名思义该方法返回的没有重复值的datarow序列

var dt = new DataTable();
dt.Columns.Add("A", typeof(int));

var newRow1 = dt.NewRow();
var newRow2 = dt.NewRow();

newRow1["A"] = 1;
newRow2["A"] = 2;
newRow3["A"] = 2;

dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);
dt.Rows.Add(newRow3);

// 重点看这里
IEnumerable<DataRow> rows = dt.AsEnumerbale();
// 去重复
IEnumerable<DataRow> distinctRows = rows.Distinct(DataRowComparer.Default);

foreach(var row in distictRows)
  Console.WriteLine(row["A"].ToString());

// 结果
// 1
// 2

注意,这里的 DataRowComparer 是一个静态类,属性 Default 表示返回单一的DataRow实例

Except, 找到DataRow序列A中在datarow序列B中没有的datarow序列

var dt1 = new DataTable();
dt1.Columns.Add("A", typeof(int));

var dt2 = new DataTable();
dt2.Columns.Add("A", typeof(int));

dt1.Rows.Add(new object[] { 1 });
dt1.Rows.Add(new object[] { 2 });

dt2.Rows.Add(new object[] { 2 });
dt2.Rows.Add(new object[] { 3 });

// 重点看这里
IEnumerable<DataRow> rows1 = dt1.AsEnumerable();
IEnumerable<DataRow> rows2 = dt2.AsEnumerable();

// 获取rows1中在rows2里没有包含的datarow序列
var rows3 = rows1.Except(rows2, DataRowComparer.Default);

foreach (var row in rows3)
  Console.WriteLine(row["A"].ToString());

// 结果
// 1

Intersect, 两个DataRow序列的交集

var dt1 = new DataTable();
dt1.Columns.Add("A", typeof(int));

var dt2 = new DataTable();
dt2.Columns.Add("A", typeof(int));

dt1.Rows.Add(new object[]{1});
dt1.Rows.Add(new object[]{2});

dt2.Rows.Add(new object[]{2});
dt2.Rows.Add(new object[]{3});

// 重点看这里
IEnumerable<DataRow> rows1 = dt1.AsEnumerbale();
IEnumerable<DataRow> rows2 = dt2.AsEnumerbale();

// 获取rows1与rows2共有的datarow序列
rows1.Intersect(row2, DataRowComparer.Default); 

foreach(var row in rows1) 
  Console.WriteLine(row["A"].ToString());
// 结果
// 2

Union,合并两个datarow序列

var dt1 = new DataTable();
dt1.Columns.Add("A", typeof(int));

var dt2 = new DataTable();
dt2.Columns.Add("A", typeof(int));

dt1.Rows.Add(new object[] { 1 });
dt1.Rows.Add(new object[] { 2 });

dt2.Rows.Add(new object[] { 2 });
dt2.Rows.Add(new object[] { 3 });

// 重点看这里
IEnumerable<DataRow> rows1 = dt1.AsEnumerable();
IEnumerable<DataRow> rows2 = dt2.AsEnumerable();

// 合并rows1与rows2
var row3 = rows1.Union(rows2, DataRowComparer.Default);

foreach (var row in row3)
  Console.WriteLine(row["A"].ToString());
// 结果
// 1
// 2
// 3

SequenceEqual,判断两个dataorw序列是否相等

var dt1 = new DataTable();
dt1.Columns.Add("A", typeof(int));

var dt2 = new DataTable();
dt2.Columns.Add("A", typeof(int));

dt1.Rows.Add(new object[]{1});
dt1.Rows.Add(new object[]{2});

dt2.Rows.Add(new object[]{2});
dt2.Rows.Add(new object[]{3});

// 重点看这里
IEnumerable<DataRow> rows1 = dt1.AsEnumerbale();
IEnumerable<DataRow> rows2 = dt2.AsEnumerbale();

// 合并rows1与rows2
var equal = rows1.SequenceEqual(row2, DataRowComparer.Default); 

Console.WriteLine(equal.ToString());

// 结果
// false

4. linq 对 DataColumn 操作

在了解了对datarow的操作后,我们再来了解一下对datacolumn的操作

Field<T> , 它是一个获取当前行(datarow)的某一列值的静态扩展方法,它具有三种重载参数,类型分别是DataColumn, String, Int,在这里建议大家使用string 类型参数,明确是取哪一列,语句阅读上更流畅。

var dt = new DataTable();
dt.Columns.Add("A", typeof(int));

var newRow1 = dt.NewRow();
var newRow2 = dt.NewRow();

newRow1["A"] = 1;
newRow2["A"] = 2;

dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);

IEnumerable<DataRow> rows = dt.AsEnumerbale();

// 重点看这里
foreach(var val in rows.Select(e => e.Field<int>("A"))
  Console.WriteLine(val.ToString());

SetField<T> , 该方法刚好是对当前行某一列进行赋值操作,同样也具有三种重载参数DataColumn, String, Int,在这里建议大家使用string 类型参数,明确是取哪一列,语句阅读上更流畅。

var dt = new DataTable();
dt.Columns.Add("A", typeof(int));

var newRow1 = dt.NewRow();
var newRow2 = dt.NewRow();

newRow1["A"] = 1;
newRow2["A"] = 2;

dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);

IEnumerable<DataRow> rows = dt.AsEnumerbale();

// 重点看这里
foreach(var row in rows)
  row.SetField<int>("A", row.Field<int>("A")+10);

foreach(var val in rows.Select(e => e.Field<int>("a")))
  Console.WriteLine(val.ToString())

// 结果
// 11
// 12

5. CopyToDataTable<DataRow>,该方法是将datarow序列组成一个新的DataTable

// 已知一个DataTable
var dt = new DataTable();

// 获取一个DataRow序列
var rows = dt.AsEnumerable();

//经过一系列操作
// ....

//获取一个新的DataTable
var newDt = rows.CopyToDataTable();

至此,我们对linq to DataSet 有了一个基本认识与了解,那么下面我们将了解另一个应用 linq to xml

 linq to XML

在实际应用中,并不需要我们使用linq对xml对象进行操作,因为MS已经提供了封装对xml的linq操作的对象,我们一起来简单的了解下有哪些对象。

1.命名空间,linq to xml 需要如下命名空间

using System.Linq;
using System.Xml.Linq;

2. linq to xml 主要类型对象

  • XDocument : 表示 XML 文档
  • XElement : 表示一个 XML 元素
  • XAttribute : 表示一个 XML 特性(节点属性)
  • XNamespace : 表示一个 XML 命名空间
  • XCData : 表示一个包含 CDATA 的文本节点(注释)
  • XDeclaration : 表示一个 XML 声明

 // 创建一个XML文档
var xDoc = new XDocument(
  // 定义声明
  new XDeclaration("1.0", "utf-8", "yes"),
    // 添加根节点
    new XElement("root",
      // 添加子节点1,并添加节点属性“name”
      new XElement("item1", new XAttribute("name","属性"), "子节点1"),
      // 添加子节点2,并添加内容注释CDATA
      new XElement("item2", new XCData("注释"))));

// 输出结果
//<?xml version="1.0" encoding="utf-8" standalone="yes"?>
//<root>
// <item1 name="属性">子节点1</item1>
// <item2><![CDATA[注释]]></item2>
//</root>

2. 输出XML文档,当我们创建好一个xml文档对象时,调用该对象的方法 Save 即可,如下:

// 创建一个XML文档
var xDoc = new XDocument(
  // 定义声明
  new XDeclaration("1.0", "utf-8", "yes"),
    // 添加根节点
    new XElement("root",
      // 添加子节点1,并添加节点属性“name”
      new XElement("item1", new XAttribute("name","属性"), "子节点1"),
      // 添加子节点2,并添加内容注释CDATA
      new XElement("item2", new XCData("注释"))));

// 输出XML文档
xDoc.Save("demo.xml");

3. 导入xml文档,如果已知一个XML文本文件,我们需要获取这个xml文本文件XDocment对象时,可以执行改对象方法 Load,该方法具有八种参数重载,参数类型分别是Stream,String,TextReader,XmlReader。下面的示例中使用的是 string 类型参数传递

XDocment xDoc = XDocument.Load("demo.xml");

4. XNode 抽象基类,表示 XML 树中节点的抽象概念(元素、注释、文档类型、处理指令或文本节点),简单理解就是我们可以把XML的内容每一个部分都视为节点,也就是说它是类型的基类,并提供了大量的操作xml方法。

摘自MSDN:

XNode 是以下类型的抽象公共基类:

  • XComment
  • XContainer
  • XDocumentType
  • XProcessingInstruction
  • XText

XContainer 是以下类型的抽象公共基类:

  • XDocument
  • XElement

派生自 XContainer 的类的对象可以包含子节点。

5. 常用遍历方法

  • DescendantNodes : 按文档顺序返回此文档或元素的子代节点集合。
  • Elements : 按文档顺序返回此元素或文档的子元素集合

var xDoc = XDocument.Load("demo.xml");

IEnumerable<XNode> nodex = xDoc.DescendantNodes();
IEnumerable<XElement> elems = xDoc.Elements();

当我们获取到到节点或者元素的序列后就可以对这些对象进行常规的LINQ操作,例如运用前两篇介绍的知识。

由于篇幅关系,这里就不逐一去讲解每个LINQ TO XML的API了,感兴趣的读者可以去msdn查阅System.Xml.Linq命名空间下的操作对象。

总 结

(吐槽)当我写完这篇文章时,自我感觉很枯燥,通篇介绍的都是API封装没有体现出LINQ的新意,想删掉这篇文章的冲动都有,但是一想既然我们要学习LINQ,这些东西还是需要适当了解与接触,所以还是硬着头皮写下来了,如果你能看完整篇文章,那真的非常感谢,感谢你的支持。

linq to xml 在效率上和 xml 的 xpath 差不了多少,所以在什么情况下怎么使用任君选择,并不需要强制使用的。

linq to dataset 小数据的时候可以这么干,但是数据量大时候,我建议不要这么干,首先要执行AsEnumberable这样一个耗时的方法划不来,不如直接上foreach遍历。

最终篇将和大家分享并讨论最受大家所熟知的LINQ TO SQL,还是希望大家给予一点期待吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

[!--infotagslink--]

相关文章

  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • photoshop画斜线/直线/虚线的入门级教程

    这篇文章算是超级入门级别的了,我们下面来给各位介绍在photoshop画斜线/直线/虚线的教程了,希望下面这篇文章给你入门来帮助。 PS怎么画斜线 选择铅笔工具,或者画笔...2016-09-14
  • 20分钟MySQL基础入门

    这篇文章主要为大家分享了20分钟MySQL基础入门教程,快速掌握MySQL基础知识,真正了解MySQL,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-12-02
  • C#使用linq对数组进行筛选排序的方法

    这篇文章主要介绍了C#使用linq对数组进行筛选排序的方法,实例分析了C#实用linq扩展进行数组排序的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C#中的Linq Intersect与Except方法使用实例

    这篇文章主要介绍了C#中的Linq Intersect与Except方法使用实例,本文直接给出示例代码,需要的朋友可以参考下...2020-06-25
  • 详解Servlet入门级设置(超详细 IDEA2020版)

    这篇文章主要介绍了详解Servlet入门级设置(超详细 IDEA2020版),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-04
  • php入门教程(类实例教程)

    这里主要讲到关于在php教程类的调用,申请明,使用以前各种类的实例方法与操作过程,让你清楚的知道php类的construct destruct clone call wake sleep用法。 简单购物车...2016-11-25
  • MySQL的InnoDB引擎入门学习教程

    MySQL发展到今天,InnoDB引擎已经作为绝对的主力,除了像大数据量分析等比较特殊领域需求外,它适用于众多场景。然而,仍有不少开发者还在“执迷不悟”的使用MyISAM引擎,觉得对InnoDB无法把握好,还是MyISAM简单省事,还能支持快...2015-11-24
  • 阿里云ECS服务器入门使用流程(新手必看教程)

    这篇文章主要介绍了阿里云ECS服务器入门使用流程(新手必看教程),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-07-13
  • php入门级教程:PHP大小写问题

    PHP大小写问题算是一个入门级的教程了,在此小编为php初学者介绍php开发中大小写的一些例子,希望可以帮助到各位。 今天写代码的时候发现自己代码的一处错误: $m_cate...2016-11-25
  • 一篇文章带你了解C语言:入门基础(2)

    这篇文章主要介绍了C语言入门之基础知识详解,文中有非常详细的C语言使用教程及相关基础知识,对正在学习c语言的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-08-04
  • c# Linq常用的小技巧

    这篇文章主要介绍了c# Linq常用的小技巧,文中讲解非常详细,示例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-11-03
  • Springboot入门案例及部署项目的详细过程

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,本文给大家分享一个入门案例使用Springboot1.5.9搭建,具体配置部署过程跟随小编一起看看吧...2021-07-12
  • 一篇入门的 Class 文章

    刚在大略浏览了一下首页更新的那篇有关Class的文章(指PHPE的那篇 http://www.phpe.net/articles/389.shtml ),很不错,建议看看。 对类的摸索~~俺用了半年时间才大概理解类的...2016-11-25
  • php入门教程:php rtrim()实例教程

    php入门教程:php rtrim()实例教程 定义和用法 该rtrim ( )函数将删除空格或其他预先确定的性质从右侧的一个字符串。 语法 rtrim(string,charlist) 参数说明 字符...2016-11-25
  • 一篇文章带你入门java算术运算符(加减乘除余,字符连接)

    这篇文章主要介绍了Java基本数据类型和运算符,结合实例形式详细分析了java基本数据类型、数据类型转换、算术运算符、逻辑运算符等相关原理与操作技巧,需要的朋友可以参考下...2021-08-05
  • php基础入门篇-文件和目录操作

    一篇关于php 入门的朋友参考的关于文件和目录的各种操作函数与实例应用,有需要的朋友可以简单的参考一下。 本章可以算是上一章的延续,介绍了除文件实际内容之外的...2016-11-25
  • mongodb基础入门_动力节点Java学院整理

    这篇文章主要为大家详细介绍了mongodb基础入门的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-11
  • 带你入门Java的集合

    Java的集合类型都是对java.util包中Collection接口的继承,这里我们主要介绍依赖于collection的一些主分支,一起来看一下Java中的collection集合类型总结...2021-07-07
  • php入门教程第一课简单的PHP显示与嵌入PHP

    php入门教程第一课简单的PHP显示与嵌入PHP 代码如下 复制代码 <html> <head> <title>第一个php教程程序</title> </head> <body> <?php...2016-11-25