详解LINQ入门(下篇)
前言
终于来到下篇了,通过上篇,和中篇,我们了解了linq的基本语句,对应linq我们又了解到lambda表达式,静态扩展方法,以及linq的延迟加载的特性,那么在本篇文章中我们将分享学习一下linq对于我们开发中常用到的对象的操作应用。如果没有阅读过上篇的请点击这里,如果没有阅读中篇的请点击这里
linqtoDataSet
对于做.net开发的有谁不知道DataSet,DataTable,DataRow,DataColumn这些对象,如果你真的不知道,那好吧建议你到菜市场买2块豆腐撞死算了>_<。也许你会惊讶,哇靠!linq能操作这些?答案是肯定的。那么我们来看看linq是怎么操作的。
1.命名空间,如果需要linq操作DataSet,需要以下命名空间
usingSystem.Data; usingSystem.Linq;
2.关键方法AsEnumerable,该方法为一个静态扩展方法,他将DataTable转换为一个IEnumerable
vardt=newDataTable(); dt.Columns.Add("A",typeof(int)); varnewRow1=dt.NewRow(); varnewRow2=dt.NewRow(); newRow1["A"]=1; newRow2["A"]=2; dt.Rows.Add(newRow1); dt.Rows.Add(newRow2); //重点看这里 IEnumerablerows=dt.AsEnumerbale(); foreach(rowinrows) Console.WriteLine(row["A"].ToString());
从这段代码看,并没有什么实质意义,如果这样去遍历datarow就是脱裤子放屁,多此一举。但是这样做的目只有一个为下面的linq操作做铺垫。
3.linq对DataRow操作,以下举例一些linq特有的常用datarow操作
Distinct,顾名思义该方法返回的没有重复值的datarow序列
vardt=newDataTable(); dt.Columns.Add("A",typeof(int)); varnewRow1=dt.NewRow(); varnewRow2=dt.NewRow(); newRow1["A"]=1; newRow2["A"]=2; newRow3["A"]=2; dt.Rows.Add(newRow1); dt.Rows.Add(newRow2); dt.Rows.Add(newRow3); //重点看这里 IEnumerablerows=dt.AsEnumerbale(); //去重复 IEnumerable distinctRows=rows.Distinct(DataRowComparer.Default); foreach(varrowindistictRows) Console.WriteLine(row["A"].ToString()); //结果 //1 //2
注意,这里的DataRowComparer是一个静态类,属性Default表示返回单一的DataRow实例
Except,找到DataRow序列A中在datarow序列B中没有的datarow序列
vardt1=newDataTable(); dt1.Columns.Add("A",typeof(int)); vardt2=newDataTable(); dt2.Columns.Add("A",typeof(int)); dt1.Rows.Add(newobject[]{1}); dt1.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{3}); //重点看这里 IEnumerablerows1=dt1.AsEnumerable(); IEnumerable rows2=dt2.AsEnumerable(); //获取rows1中在rows2里没有包含的datarow序列 varrows3=rows1.Except(rows2,DataRowComparer.Default); foreach(varrowinrows3) Console.WriteLine(row["A"].ToString()); //结果 //1
Intersect,两个DataRow序列的交集
vardt1=newDataTable(); dt1.Columns.Add("A",typeof(int)); vardt2=newDataTable(); dt2.Columns.Add("A",typeof(int)); dt1.Rows.Add(newobject[]{1}); dt1.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{3}); //重点看这里 IEnumerablerows1=dt1.AsEnumerbale(); IEnumerable rows2=dt2.AsEnumerbale(); //获取rows1与rows2共有的datarow序列 rows1.Intersect(row2,DataRowComparer.Default); foreach(varrowinrows1) Console.WriteLine(row["A"].ToString()); //结果 //2
Union,合并两个datarow序列
vardt1=newDataTable(); dt1.Columns.Add("A",typeof(int)); vardt2=newDataTable(); dt2.Columns.Add("A",typeof(int)); dt1.Rows.Add(newobject[]{1}); dt1.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{3}); //重点看这里 IEnumerablerows1=dt1.AsEnumerable(); IEnumerable rows2=dt2.AsEnumerable(); //合并rows1与rows2 varrow3=rows1.Union(rows2,DataRowComparer.Default); foreach(varrowinrow3) Console.WriteLine(row["A"].ToString()); //结果 //1 //2 //3
SequenceEqual,判断两个dataorw序列是否相等
vardt1=newDataTable(); dt1.Columns.Add("A",typeof(int)); vardt2=newDataTable(); dt2.Columns.Add("A",typeof(int)); dt1.Rows.Add(newobject[]{1}); dt1.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{2}); dt2.Rows.Add(newobject[]{3}); //重点看这里 IEnumerablerows1=dt1.AsEnumerbale(); IEnumerable rows2=dt2.AsEnumerbale(); //合并rows1与rows2 varequal=rows1.SequenceEqual(row2,DataRowComparer.Default); Console.WriteLine(equal.ToString()); //结果 //false
4.linq对DataColumn操作
在了解了对datarow的操作后,我们再来了解一下对datacolumn的操作
Field
vardt=newDataTable(); dt.Columns.Add("A",typeof(int)); varnewRow1=dt.NewRow(); varnewRow2=dt.NewRow(); newRow1["A"]=1; newRow2["A"]=2; dt.Rows.Add(newRow1); dt.Rows.Add(newRow2); IEnumerablerows=dt.AsEnumerbale(); //重点看这里 foreach(varvalinrows.Select(e=>e.Field ("A")) Console.WriteLine(val.ToString());
SetField
vardt=newDataTable(); dt.Columns.Add("A",typeof(int)); varnewRow1=dt.NewRow(); varnewRow2=dt.NewRow(); newRow1["A"]=1; newRow2["A"]=2; dt.Rows.Add(newRow1); dt.Rows.Add(newRow2); IEnumerablerows=dt.AsEnumerbale(); //重点看这里 foreach(varrowinrows) row.SetField ("A",row.Field ("A")+10); foreach(varvalinrows.Select(e=>e.Field ("a"))) Console.WriteLine(val.ToString()) //结果 //11 //12
5.CopyToDataTable
//已知一个DataTable vardt=newDataTable(); //获取一个DataRow序列 varrows=dt.AsEnumerable(); //经过一系列操作 //.... //获取一个新的DataTable varnewDt=rows.CopyToDataTable();
至此,我们对linqtoDataSet有了一个基本认识与了解,那么下面我们将了解另一个应用linqtoxml
linqtoXML
在实际应用中,并不需要我们使用linq对xml对象进行操作,因为MS已经提供了封装对xml的linq操作的对象,我们一起来简单的了解下有哪些对象。
1.命名空间,linqtoxml需要如下命名空间
usingSystem.Linq; usingSystem.Xml.Linq;
2.linqtoxml主要类型对象
- XDocument:表示XML文档
- XElement:表示一个XML元素
- XAttribute:表示一个XML特性(节点属性)
- XNamespace:表示一个XML命名空间
- XCData:表示一个包含CDATA的文本节点(注释)
- XDeclaration:表示一个XML声明
//创建一个XML文档 varxDoc=newXDocument( //定义声明 newXDeclaration("1.0","utf-8","yes"), //添加根节点 newXElement("root", //添加子节点1,并添加节点属性“name” newXElement("item1",newXAttribute("name","属性"),"子节点1"), //添加子节点2,并添加内容注释CDATA newXElement("item2",newXCData("注释")))); //输出结果 // //// 子节点1 // //
2.输出XML文档,当我们创建好一个xml文档对象时,调用该对象的方法Save即可,如下:
//创建一个XML文档 varxDoc=newXDocument( //定义声明 newXDeclaration("1.0","utf-8","yes"), //添加根节点 newXElement("root", //添加子节点1,并添加节点属性“name” newXElement("item1",newXAttribute("name","属性"),"子节点1"), //添加子节点2,并添加内容注释CDATA newXElement("item2",newXCData("注释")))); //输出XML文档 xDoc.Save("demo.xml");
3.导入xml文档,如果已知一个XML文本文件,我们需要获取这个xml文本文件XDocment对象时,可以执行改对象方法Load,该方法具有八种参数重载,参数类型分别是Stream,String,TextReader,XmlReader。下面的示例中使用的是string类型参数传递
XDocmentxDoc=XDocument.Load("demo.xml");
4.XNode抽象基类,表示XML树中节点的抽象概念(元素、注释、文档类型、处理指令或文本节点),简单理解就是我们可以把XML的内容每一个部分都视为节点,也就是说它是类型的基类,并提供了大量的操作xml方法。
摘自MSDN:
XNode是以下类型的抽象公共基类:
- XComment
- XContainer
- XDocumentType
- XProcessingInstruction
- XText
XContainer是以下类型的抽象公共基类:
- XDocument
- XElement
派生自XContainer的类的对象可以包含子节点。
5.常用遍历方法
- DescendantNodes:按文档顺序返回此文档或元素的子代节点集合。
- Elements:按文档顺序返回此元素或文档的子元素集合
varxDoc=XDocument.Load("demo.xml"); IEnumerablenodex=xDoc.DescendantNodes(); IEnumerable elems=xDoc.Elements();
当我们获取到到节点或者元素的序列后就可以对这些对象进行常规的LINQ操作,例如运用前两篇介绍的知识。
由于篇幅关系,这里就不逐一去讲解每个LINQTOXML的API了,感兴趣的读者可以去msdn查阅System.Xml.Linq命名空间下的操作对象。
总结
(吐槽)当我写完这篇文章时,自我感觉很枯燥,通篇介绍的都是API封装没有体现出LINQ的新意,想删掉这篇文章的冲动都有,但是一想既然我们要学习LINQ,这些东西还是需要适当了解与接触,所以还是硬着头皮写下来了,如果你能看完整篇文章,那真的非常感谢,感谢你的支持。
linqtoxml在效率上和xml的xpath差不了多少,所以在什么情况下怎么使用任君选择,并不需要强制使用的。
linqtodataset小数据的时候可以这么干,但是数据量大时候,我建议不要这么干,首先要执行AsEnumberable这样一个耗时的方法划不来,不如直接上foreach遍历。
最终篇将和大家分享并讨论最受大家所熟知的LINQTOSQL,还是希望大家给予一点期待吧。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。