LINQ入门(下篇)

来自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=172
GPS平台、网站建设、软件开发、系统运维,找森大网络科技!
http://cnsendnet.taobao.comphp

到如今为止你还未触碰LINQ,那进来吧 —— LINQ入门(下篇)
前 言
  终于来到下篇了,经过上篇,和中篇,咱们了解了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>的序列node

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
  1. 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;ide

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());spa

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

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

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,仍是但愿你们给予一点期待吧。
  感谢阅读,若是有说的不对的地方请指正,谢谢。

来自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=172
GPS平台、网站建设、软件开发、系统运维,找森大网络科技!
http://cnsendnet.taobao.com
相关文章
相关标签/搜索