大多數應用程式是以數據爲中心的,但是大多數數據存儲庫是關係資料庫。多年來,設計人員和開發人員一直在基於對象模型設計應用程式。
這些對象負責連接到數據訪問組件,稱爲數據訪問層(DAL)。這裡我們有三點要考慮:
應用程式中所需的所有數據都不存儲在同一個源中。源可以是關係資料庫、某些業務對象、XML文件或web服務。
訪問內存中的對象比從資料庫或XML文件訪問數據更簡單、成本更低。
訪問的數據不是直接使用的,而是需要排序、排序、分組、更改等。
因此,如果有一種工具可以使所有類型的數據訪問變得容易,允許將來自這些不同數據源的數據連接起來,並執行標準的數據處理操作,只需幾行代碼,那將是非常有幫助的。
LINQ或語言集成查詢就是這樣一個工具。LINQ是.NETFramework3.5及其託管語言的一組擴展,這些語言將查詢設置爲對象。它定義了一個通用語法和一個編程模型來使用一種通用語言查詢不同類型的數據。
諸如Select、Project、Join、Group、Partition、Set操作等關係運算符是在LINQ中實現的,.Net framework 3.5中的C#和VB編譯器支持LINQ語法,因此無需藉助ADO.Net就可以使用已配置的數據存儲。
例如,查詢Northwind資料庫中的Customers表,使用C#中的LINQ查詢,代碼如下:
var data = from c in dataContext.Customers where c.Country == "Spain" select c;
哪裡:
「from」關鍵字在邏輯上循環遍歷集合的內容。
對集合中的每個對象計算具有「where」關鍵字的表達式。
「select」語句選擇要添加到返回列表中的計算對象。
「var」關鍵字用於變量聲明。由於返回對象的確切類型未知,它指示將動態推斷信息。
LINQ查詢可以應用於繼承自IEnumerable<T>的任何數據承載類,這裡T是任何數據類型,例如List<Book>。
讓我們看一個例子來理解這個概念。示例使用以下類:Books.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 Java 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; } }
使用此類的網頁有一個簡單的標籤控制項,用於顯示書籍的標題。Page_Load事件創建書籍列表,並使用LINQ query返回標題:
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 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
LINQ Operators
除了目前使用的運算符外,還有其他幾個運算符,它們實現了所有查詢子句。讓我們看看一些運算符和子句。
The Join clause
SQL中的「join子句」用於連接兩個數據表,並顯示包含兩個表中的列的數據集。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[] sd = { new 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 = "004", pages=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加載事件處理程序中添加代碼,以便使用join子句查詢兩個表:
protected void Page_Load(object sender, EventArgs e) { IEnumerable<Books> books = Books.GetBooks(); IEnumerable<Salesdetails> sales = Salesdetails.getsalesdetails(); var booktitles = from b in books join s in sales on b.ID equals s.ID select new { Name = b.Title, Pages = s.pages }; foreach (var title in booktitles) lblbooks.Text += String.Format("{0} <br />", title); }
結果頁面如下所示:
The Where clause
「where子句」允許向查詢添加一些條件篩選器。例如,如果要查看頁數超過500的書本,請將「頁面加載」事件處理程序更改爲:
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的行:
Orderby and Orderbydescending Clauses
這些子句允許對查詢結果進行排序。要查詢按價格排序的書籍標題、頁數和價格,請在頁面加載事件處理程序中編寫以下代碼:
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};
返回的元組是:
The Let clause
let子句允許定義一個變量並爲其分配一個根據數據值計算的值。例如,要計算上述兩個銷售的總銷售額,您需要計算:
TotalSale = Price of the Book * Sales
爲此,請在頁面加載事件處理程序中添加以下代碼段:
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};
生成的查詢頁面如下所示: