詳解LINQ入門(下篇)
前 言
終于來到下篇了,通過上篇,和中篇,我們了解了linq的基本語句,對應(yīng)linq我們又了解到lambda表達(dá)式,靜態(tài)擴(kuò)展方法,以及l(fā)inq的延遲加載的特性,那么在本篇文章中我們將分享學(xué)習(xí)一下linq對于我們開發(fā)中常用到的對象的操作應(yīng)用。如果沒有閱讀過上篇的請點擊這里,如果沒有閱讀中篇的請點擊這里
linq to DataSet
對于做.net 開發(fā)的有誰不知道DataSet,DataTable,DataRow,DataColumn這些對象,如果你真的不知道,那好吧建議你到菜市場買2塊豆腐撞死算了>_<。也許你會驚訝,哇靠!linq能操作這些?答案是肯定的。那么我們來看看linq是怎么操作的。
1. 命名空間,如果需要linq操作DataSet,需要以下命名空間
using System.Data; using System.Linq;
2. 關(guān)鍵方法 AsEnumerable,該方法為一個靜態(tài)擴(kuò)展方法,他將DataTable轉(zhuǎn)換為一個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());
從這段代碼看,并沒有什么實質(zhì)意義,如果這樣去遍歷datarow就是脫褲子放屁,多此一舉。但是這樣做的目只有一個為下面的linq操作做鋪墊。
3. linq 對 DataRow 操作,以下舉例一些linq特有的常用datarow操作
Distinct,顧名思義該方法返回的沒有重復(fù)值的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(); // 去重復(fù) IEnumerable<DataRow> distinctRows = rows.Distinct(DataRowComparer.Default); foreach(var row in distictRows) Console.WriteLine(row["A"].ToString()); // 結(jié)果 // 1 // 2
注意,這里的 DataRowComparer 是一個靜態(tài)類,屬性 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()); // 結(jié)果 // 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()); // 結(jié)果 // 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()); // 結(jié)果 // 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()); // 結(jié)果 // false
4. linq 對 DataColumn 操作
在了解了對datarow的操作后,我們再來了解一下對datacolumn的操作
Field<T> , 它是一個獲取當(dāng)前行(datarow)的某一列值的靜態(tài)擴(kuò)展方法,它具有三種重載參數(shù),類型分別是DataColumn, String, Int,在這里建議大家使用string 類型參數(shù),明確是取哪一列,語句閱讀上更流暢。
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> , 該方法剛好是對當(dāng)前行某一列進(jìn)行賦值操作,同樣也具有三種重載參數(shù)DataColumn, String, Int,在這里建議大家使用string 類型參數(shù),明確是取哪一列,語句閱讀上更流暢。
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()) // 結(jié)果 // 11 // 12
5. CopyToDataTable<DataRow>,該方法是將datarow序列組成一個新的DataTable
// 已知一個DataTable var dt = new DataTable(); // 獲取一個DataRow序列 var rows = dt.AsEnumerable(); //經(jīng)過一系列操作 // .... //獲取一個新的DataTable var newDt = rows.CopyToDataTable();
至此,我們對linq to DataSet 有了一個基本認(rèn)識與了解,那么下面我們將了解另一個應(yīng)用 linq to xml
linq to XML
在實際應(yīng)用中,并不需要我們使用linq對xml對象進(jìn)行操作,因為MS已經(jīng)提供了封裝對xml的linq操作的對象,我們一起來簡單的了解下有哪些對象。
1.命名空間,linq to xml 需要如下命名空間
using System.Linq; using System.Xml.Linq;
2. linq to xml 主要類型對象
- XDocument : 表示 XML 文檔
- XElement : 表示一個 XML 元素
- XAttribute : 表示一個 XML 特性(節(jié)點屬性)
- XNamespace : 表示一個 XML 命名空間
- XCData : 表示一個包含 CDATA 的文本節(jié)點(注釋)
- XDeclaration : 表示一個 XML 聲明
// 創(chuàng)建一個XML文檔 var xDoc = new XDocument( // 定義聲明 new XDeclaration("1.0", "utf-8", "yes"), // 添加根節(jié)點 new XElement("root", // 添加子節(jié)點1,并添加節(jié)點屬性“name” new XElement("item1", new XAttribute("name","屬性"), "子節(jié)點1"), // 添加子節(jié)點2,并添加內(nèi)容注釋CDATA new XElement("item2", new XCData("注釋")))); // 輸出結(jié)果 //<?xml version="1.0" encoding="utf-8" standalone="yes"?> //<root> // <item1 name="屬性">子節(jié)點1</item1> // <item2><![CDATA[注釋]]></item2> //</root>
2. 輸出XML文檔,當(dāng)我們創(chuàng)建好一個xml文檔對象時,調(diào)用該對象的方法 Save 即可,如下:
// 創(chuàng)建一個XML文檔 var xDoc = new XDocument( // 定義聲明 new XDeclaration("1.0", "utf-8", "yes"), // 添加根節(jié)點 new XElement("root", // 添加子節(jié)點1,并添加節(jié)點屬性“name” new XElement("item1", new XAttribute("name","屬性"), "子節(jié)點1"), // 添加子節(jié)點2,并添加內(nèi)容注釋CDATA new XElement("item2", new XCData("注釋")))); // 輸出XML文檔 xDoc.Save("demo.xml");
3. 導(dǎo)入xml文檔,如果已知一個XML文本文件,我們需要獲取這個xml文本文件XDocment對象時,可以執(zhí)行改對象方法 Load,該方法具有八種參數(shù)重載,參數(shù)類型分別是Stream,String,TextReader,XmlReader。下面的示例中使用的是 string 類型參數(shù)傳遞
XDocment xDoc = XDocument.Load("demo.xml");
4. XNode 抽象基類,表示 XML 樹中節(jié)點的抽象概念(元素、注釋、文檔類型、處理指令或文本節(jié)點),簡單理解就是我們可以把XML的內(nèi)容每一個部分都視為節(jié)點,也就是說它是類型的基類,并提供了大量的操作xml方法。
摘自MSDN:
XNode 是以下類型的抽象公共基類:
- XComment
- XContainer
- XDocumentType
- XProcessingInstruction
- XText
XContainer 是以下類型的抽象公共基類:
- XDocument
- XElement
派生自 XContainer 的類的對象可以包含子節(jié)點。
5. 常用遍歷方法
- DescendantNodes : 按文檔順序返回此文檔或元素的子代節(jié)點集合。
- Elements : 按文檔順序返回此元素或文檔的子元素集合
var xDoc = XDocument.Load("demo.xml"); IEnumerable<XNode> nodex = xDoc.DescendantNodes(); IEnumerable<XElement> elems = xDoc.Elements();
當(dāng)我們獲取到到節(jié)點或者元素的序列后就可以對這些對象進(jìn)行常規(guī)的LINQ操作,例如運用前兩篇介紹的知識。
由于篇幅關(guān)系,這里就不逐一去講解每個LINQ TO XML的API了,感興趣的讀者可以去msdn查閱System.Xml.Linq命名空間下的操作對象。
總 結(jié)
(吐槽)當(dāng)我寫完這篇文章時,自我感覺很枯燥,通篇介紹的都是API封裝沒有體現(xiàn)出LINQ的新意,想刪掉這篇文章的沖動都有,但是一想既然我們要學(xué)習(xí)LINQ,這些東西還是需要適當(dāng)了解與接觸,所以還是硬著頭皮寫下來了,如果你能看完整篇文章,那真的非常感謝,感謝你的支持。
linq to xml 在效率上和 xml 的 xpath 差不了多少,所以在什么情況下怎么使用任君選擇,并不需要強(qiáng)制使用的。
linq to dataset 小數(shù)據(jù)的時候可以這么干,但是數(shù)據(jù)量大時候,我建議不要這么干,首先要執(zhí)行AsEnumberable這樣一個耗時的方法劃不來,不如直接上foreach遍歷。
最終篇將和大家分享并討論最受大家所熟知的LINQ TO SQL,還是希望大家給予一點期待吧。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:C# List介紹及具體用法
欄 目:C#教程
下一篇:C# ODP.NET 調(diào)用Oracle函數(shù)返回值時報錯的一個解決方案
本文標(biāo)題:詳解LINQ入門(下篇)
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/4588.html
您可能感興趣的文章
- 01-10C#中Socket通信用法實例詳解
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#類的多態(tài)性詳解
- 01-10C#創(chuàng)建不規(guī)則窗體的4種方式詳解
- 01-10C#中深度復(fù)制和淺度復(fù)制詳解
- 01-10輕松學(xué)習(xí)C#的基礎(chǔ)入門
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之隊列(Quene)實例詳解
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之順序表(SeqList)實例詳解
- 01-10C#編程實現(xiàn)連接ACCESS數(shù)據(jù)庫實例詳解
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之單鏈表(LinkList)實例詳解


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10C#中split用法實例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置