摘要:當VS2005 遇上 LINQ
當VS2005 遇上 LINQ
文/黃忠成
在【極意之道-次世代 .NET Framework 3.5 資料庫開發聖典】(好長的書名,我該取個匿稱嗎?哈)一書第三章中,有下面這段敘述:
任何支援.NET Framework 2.0的程式語言都能夠叫用LINQ所提供的查詢函式,也就是說能使用C# 2.0來呼叫LINQ Framework |
書中列出一小段程式碼,證明事實上只要是C# 2.0,就能夠使用LINQ所提供的查詢函式,前提是電腦中必須安裝.NET Framework 3.5。
那好,什麼時候我們會需要這種寫法呢?想像一下,你可以利用LINQ查詢函式來做什麼?你可以將兩個陣列Join起來、排序、Group、查詢,你也可以將兩個XML檔案Join起來,甚至可以將兩個DataTable Join起來,哦!這段敘述是否挑到你最敏感的那條神經了呢?
不過,說歸說,做歸做,如果在.NET Framework 2.0中叫用LINQ,能得到什麼好處呢?很明顯的,你原本的專案不需要做大幅度的升級,你不需要裝Visual Studio 2008,你只需安裝.NET Framework 3.5,然後加入對System.Core的參考,就能得到LINQ查詢函式的火力,再加入System.Xml.Linq的參考,就能得到LINQ To XML查詢函式,加入System.Data.DataSetExtensions的參考,就能將兩個DataTable Join起來。
但,有了這些好處,事情真的會比較簡單嗎?那得視情況而定,在沒有LINQ Expression支援下使用LINQ查詢函式,有時會將事情變的複雜,換句話說,程式碼可能變多了。不過,大部份情況下,我相信使用LINQ查詢函式會把程式碼縮短,畢竟,查詢演算法是內建在LINQ中了。
static void DemoLinq() { string[] list = new string[] { "code6421", "tom", "david", "cathy" }; IEnumerable<string> result = Enumerable.Where<string>(list, delegate(string item) { return item == "tom"; }); Console.WriteLine(Enumerable.FirstOrDefault(result)); } |
上面這段程式碼可以運行於Visual Studio 2005、Visual Studio 2008,如你使用Visual Studio 2005,請先安裝.NET Framework 3.5,然後於專案中添加對System.Core的參考(此DLL位於Program Files\ Reference Assemblies\Microsoft\Framework\3.5),完成後編譯程式,你便達到於C#,Visual Studio 2005中使用LINQ的目的。
Join 2 DataTables
我想有許多寫Windows Form程式的人,都曾經對於如何Join兩個DataTable困擾過,事實上這很簡單,只要建另一個DataTable,一個蘿蔔一個坑的填即可。
不過有了LINQ To DataSet,一切都變的簡單且直覺,但!缺少了LINQ Expression的C# 2.0,只憑LINQ 查詢函式來做,可以把這件事變簡單嗎?
using System.Data.SqlClient; ........ static IEnumerable<JoinData> JoinTables() { using (SqlConnection conn = new SqlConnection( "Data Source=JEFFRAY;Initial Catalog=Northwind;Integrated Security=True")) { SqlDataAdapter adapter1 = new SqlDataAdapter("SELECT * FROM Customers", conn); SqlDataAdapter adapter2 = new SqlDataAdapter("SELECT * FROM Orders", conn); DataTable dt1 = new DataTable("Customers"); DataTable dt2 = new DataTable("Orders"); adapter1.Fill(dt1); adapter2.Fill(dt2); return Enumerable.Join<DataRow,DataRow,string,JoinData>( DataTableExtensions.AsEnumerable(dt2), DataTableExtensions.AsEnumerable(dt1), delegate(DataRow s1) { return s1.IsNull("CustomerID") ? null : (string)s1["CustomerID"]; }, delegate(DataRow s2) { return s2.IsNull("CustomerID") ? null : (string)s2["CustomerID"]; }, delegate(DataRow s1,DataRow s2) { JoinData result = new JoinData(); result.OrderID = s1.IsNull("OrderID") ? -1 : (int)s1["OrderID"]; result.CompanyName = s2.IsNull("CompanyName") ? string.Empty : (string)s2["CompanyName"]; return result; }); } } ......... public class JoinData { private int _orderID; private string _companyName; public int OrderID { get { return _orderID; } set { _orderID = value; } } public string CompanyName { get { return _companyName; } set { _companyName = value; } } } |
這個程式需要引用System.Data.DataSetExtnesions.DLL,她與System.Core位於同一目錄下,JoinTables的函式傳回值頃印結果如下:
10779,Morgenstern Gesundkost 10780,LILA-Supermercado 10781,Wartian Herkku 10782,Cactus Comidas para llevar 10783,Hanari Carnes 10784,Magazzini Alimentari Riuniti 10785,GROSELLA-Restaurante 10786,Queen Cozinha 10787,La maison d'Asie 10788,QUICK-Stop 10789,Folies gourmandes 10790,Gourmet Lanchonetes 10791,Frankenversand 10792,Wolski Zajazd 10793,Around the Horn 10794,Que Delicia 10795,Ernst Handel 10796,HILARION-Abastos 10797,Drachenblut Delikatessen 10798,Island Trading 10799,Koniglich Essen 10800,Seven Seas Imports .......................................... |