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
相關文章
相關標籤/搜索