大多數應用程式都是以資料為中心的,然而大多數的資料倉儲是關係型資料庫。這些年,設計者和開發者設計了基於物件模型的應用程式。
物件來負責連接存取資料的元件-稱為資料存取層( DAL )。這裡我們需要考慮三點:
一個應用程式所需的所有資料可以不儲存在一個資源中。這個資源可以是關係型資料庫、業務物件、XML檔案或是一個WEB伺服器。
存取記憶體中的物件要比存取資料庫、XML檔案中的資料更簡單,更廉價。
被存取的資料不是直接使用的,而是被轉存、排序、分組、修改等。
因此如果存在只是用幾行程式碼就能實現輕易整合各種各樣的數據——可以整合來自不同來源的數據,並且能夠執行基本的數據操作的工具,那將非常有用。
語言整合查詢( LINQ )就是上述那樣的一種工具。 LINQ 是.NET Framework 3.5 的擴充集且它的管理語言使查詢更類似於是一種物件。它定義了一種通用的語法和程式模型,使我們可以使用一種慣用的語法完成來尋找不同類型的資料。
相關操作像查找、工程、連結、分組、分區、集合操作等可以在LINQ 中使用,並且在.NET Framework 3.5 中的C# 和VB 編譯器支援LINQ 的語法,這使得它可以透過配置資料來存儲,而不需要求助於ADO.NET。
舉個例子,在Northwind 資料庫中查詢Constomers 這張表,使用C# 中的LINQ ,程式碼應該是這樣:
var data = from c in dataContext.Customerswhere c.Country == "Spain"select c;
其中:
from關鍵字邏輯上依序通過每個集合。
包含關鍵字where的表達式會比較集合中的每個物件。
select宣告會選擇被比較出的物件加入到清單中並傳回。
關鍵字var用於變數聲明。因為返回物件的準確類型不明確,它表明資訊需要被動態的推測。
LINQ 查詢語句可以套用在任何繼承於IEnumerable 的有資料支撐的類,這裡T 可以是任何一個資料型別,例如List< Book >。
讓我們來看一個範例理解一下概念。範例中使用瞭如下類:Book.cs
public class Books{ public string ID {get; set;} public string Title { get; set; } public decimal Price { get; set; } public DateTime DateOfRelease { get; set; } public static List<Books> GetBooks() { List<Books> list = new List<Books>(); list.Add(new Books { ID = "001", Title = "Programming in C#", Price = 634.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add(new Books { ID = "002", Title = " Learn Jave in 30 days", Price = 250.76m, DateOfRelease = Convert.ToDateTime("2011-08-15") }); list.Add(new Books { ID = "003", Title = "Programming in ASP.Net 4.0", Price = 700.00m, DateOfRelease = Convert.ToDateTime( "2011-02-05") }); list.Add(new Books { ID = "004", Title = "VB.Net Made Easy", Price = 500.99m, DateOfRelease = Convert.ToDateTime("2011-12-31") }); list.Add(new Books { ID = "005", Title = "Programming in C" , Price = 314.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add(new Books { ID = "006", Title = "Programming in C++", Price = 456.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add( new Books { ID = "007", Title = "Datebase Developement", Price = 1000.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); return list; }}
在web 網頁中使用這個類別要有簡單的標籤控制,來顯示書的標題。 Page_Load 方法建立了一個書的清單並且透過使用LINQ 查詢傳回標題:
public partial class simplequery : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { List<Books> books = Books.GetBooks(); var booktitles = from b in books select b.Title; foreach (); var booktitles = from b in books select b.Title; foreach (); var title in booktitles) lblbooks.Text += String.Format("{0} <br />", title); }}
當網頁被運行,標籤顯示查詢結果:
上面的LINQ 表達式:
var booktitles = from b in books select b.Title;
等價於下述SQL 語句:
SELECT Title from Books
除了到目前為止使用過的運算子之外,還有很多其他運算子來執行查詢子句。我們來看一些運算符和子句。
SQL 中的'join clause'用來連接兩個資料表並顯示在兩個資料表中都出現的欄位中的資料集合。 LINQ 也可以支援這種功能。為了偵測這一點,在先前的工程裡增加另一個類別名為Saledetails.cs:
public class Salesdetails{ public int sales { get; set; } public int pages { get; set; } public string ID {get; set;} public static IEnumerable<Salesdetails> getsalesdetails() { Salesdetails[] Salesdetails[] Salesdetails { newdetails() { Salesdetails[] Salesdetails[] Salesdetails { newdetails[] Salesdetails[] Salesdetails[] Salesdetails [ ID = "001", pages=678, sales = 110000}, new Salesdetails { ID = "002", pages=789, sales = 60000}, new Salesdetails { ID = "003", pages=456, sales = 40000}, new Salesdetails { ID = "0044" 900, sales = 80000}, new Salesdetails { ID = "005", pages=456, sales = 90000}, new Salesdetails { ID = "006", pages=870, sales = 50000}, new Salesdetails { ID = "007", pages=675, sales = 40000}, }; return sd.OfType<Salesdetails>(); }}
在Page_Load 函數中加入程式碼來用join 子句處理在兩個表裡完成查詢:
protected void Page_Load(object sender, EventArgs e){ IEnumerable<Books> books = Books.GetBooks(); IEnumerable<Salesdetails> sales = Salesdetails.getsalesdetails(); var booktit = from bales in sles bookin on bales bookt. equals s.ID select new { Name = b.Title, Pages = s.pages }; foreach (var title in booktitles) lblbooks.Text += String.Format("{0} <br />", title);}
結果頁顯示如下:
where 子句允許在查詢中新增篩選條件。例如,如果你想取得頁數多於500 的書目,可以改變Page_Load 方法中的句柄成下述樣子:
var booktitles = from b in books join s in sales on b.ID equals s.ID where s.pages > 500 select new { Name = b.Title, Pages = s.pages };
查詢語句只傳回那些頁數大於500 的列:
這些子句允許將查詢結果進行排序。為了查詢出標題、頁數和書的價格,並且依照價格排序,在Page_Load 方法中的句柄裡寫如下碼:
var booktitles = from b in books join s in sales on b.ID equals s.ID orderby b.Price select new { Name = b.Title, Pages = s.pages, Price = b.Price};
回傳的元組是:
let 子句允許定義一個變數並且將資料計算的一個值賦給它。舉個例子,計從上述兩個銷售值中計算總銷售值,你需要這樣計算:
TotalSale = Price of the Book * Sales
為了完成這個運算式,加入下面這個程式碼片段在Page_Load 方法的句柄裡:
let 子句允許定義一個變數並且將資料計算的一個值賦給它。舉個例子,計從上述兩個銷售值中計算總銷售值,你需要這樣計算:
var booktitles = from b in book join s in sales on b.ID equals s.ID let totalprofit = (b.Price * s.sales) select new { Name = b.Title, TotalSale = totalprofit};
查詢結果如下圖所示: