大多數(shù)應(yīng)用程序是以數(shù)據(jù)為中心的,但大多數(shù)數(shù)據(jù)存儲庫都是關(guān)系數(shù)據(jù)庫。多年來,設(shè)計人員和開發(fā)人員基于對象模型設(shè)計了應(yīng)用程序。
這些對象負(fù)責(zé)連接到數(shù)據(jù)訪問組件(稱為數(shù)據(jù)訪問層(DAL))。這里我們有三點(diǎn)需要考慮:
因此,如果有一種工具可以使得所有類型的數(shù)據(jù)訪問變得容易,從而允許來自不同數(shù)據(jù)源的數(shù)據(jù)加入并執(zhí)行標(biāo)準(zhǔn)的數(shù)據(jù)處理操作,那么只需幾行代碼就可以獲得很大的幫助。
LINQ 或語言集成查詢就是這樣一個工具。 LINQ 是對.Net Framework 3.5及其管理語言的擴(kuò)展集,它將查詢設(shè)置為對象。并定義了一個通用語法和一個編程模型,用一種通用的語言來查詢不同類型的數(shù)據(jù)。
如:Select,Project,Join,Group,Partition,Set操作等關(guān)系運(yùn)算符在LINQ中實(shí)現(xiàn),而.Net framework 3.5+
中的 C# 和VB編譯器支持LINQ語法,可以使用配置的數(shù)據(jù)存儲而不依靠使用ADO.NET。
例如,在Northwind
數(shù)據(jù)庫中查詢Customers
表,使用C#中的LINQ查詢,代碼將是:
var data = from c in dataContext.Customers
where c.Country == "Spain"
select c;
其中,
from
關(guān)鍵字在邏輯上循環(huán)了集合的內(nèi)容。where
關(guān)鍵字的表達(dá)式。select
語句選擇評估對象添加到正在返回的列表中。var
關(guān)鍵字用于變量聲明。由于返回的對象的確切類型是未知的,這表明信息將被動態(tài)推斷。LINQ查詢可以應(yīng)用于從IEnumerable <T>
繼承的任何數(shù)據(jù)承載類,這里T
是任何數(shù)據(jù)類型,例如:List <Book>
。
下面來看看一個例子來理解這個概念。打開Visual Studio 創(chuàng)建一個ASP.NET空網(wǎng)站項(xiàng)目:LinqDemo ,添加一個Web窗體頁面文件:Default.aspx -
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>LinQ示例</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h4>圖書列表示例</h4>
<asp:Label ID="lblbooks" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
該示例使用以下類:Books.cs -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Books 的摘要說明
/// </summary>
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;
}
}
使用這個類的網(wǎng)頁有一個簡單的標(biāo)簽控件,顯示書的標(biāo)題。Page_Load
事件創(chuàng)建書籍列表并通過使用LINQ查詢返回標(biāo)題:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : 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);
}
}
當(dāng)頁面執(zhí)行時,標(biāo)簽顯示查詢的結(jié)果:
上面的LINQ表達(dá)式:
var booktitles =
from b in books
select b.Title;
它相當(dāng)于下面的SQL查詢:
SELECT Title from Books
除了迄今使用的操作符外,還有其他幾個操作符,它們實(shí)現(xiàn)了所有的查詢語句。下面來看看一些運(yùn)算符和子句。
Join子句
SQL中的“Join子句” 用于連接兩個數(shù)據(jù)表,并顯示包含兩個表的列的數(shù)據(jù)集。LINQ也有這個能力。要理解這個用法,現(xiàn)在添加另一個名為 Saledetails.cs
的類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
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_Load
事件處理程序中添加代碼,以使用join
子句在兩個表上進(jìn)行查詢:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Sales : System.Web.UI.Page
{
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);
}
}
結(jié)果頁面如圖所示:
Where子句
where
子句允許向查詢添加一些條件過濾器。例如,如果要查看頁數(shù)超過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 };
該查詢僅返回頁數(shù)超過500
的那些行:
Orderby和Orderbydescending子句
這些子句允許對查詢結(jié)果進(jìn)行排序。要按照價格查詢書籍的標(biāo)題,頁數(shù)和價格,請在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子句
let
子句允許定義一個變量并為其分配一個從數(shù)據(jù)值計算出的值。例如,要計算上述兩個銷售額中的總銷售額,需要計算:
TotalSale = Price of the Book * Sales
要實(shí)現(xiàn)這一點(diǎn),請在Page_Load
事件處理程序中添加以下代碼片段:
var booktitles = from b in books
join s in sales on b.ID equals s.ID
let totalprofit = (b.Price * s.sales)
select new { Name = b.Title, TotalSale = totalprofit };
結(jié)果查詢頁面如下所示: