ASP.NET - LINQ



大多數應用程式都是以資料為中心的,但是大多數資料儲存庫都是關係資料庫。多年來,設計師和開發人員設計了基於物件模型的應用程式。

物件負責連線到資料訪問元件——稱為資料訪問層 (DAL)。這裡有三個需要考慮的要點:

  • 應用程式中所需的所有資料並非都儲存在同一個源中。該源可以是關係資料庫、某些業務物件、XML 檔案或 Web 服務。

  • 訪問記憶體中物件比訪問資料庫或 XML 檔案中的資料更簡單且成本更低。

  • 訪問的資料不會直接使用,而是需要進行排序、排列、分組、更改等操作。

因此,如果有一個工具可以輕鬆訪問各種資料,允許從不同的資料來源連線資料並執行標準資料處理操作,只需幾行程式碼,那將非常有用。

LINQ 或語言整合查詢就是這樣一種工具。LINQ 是對 .NET Framework 3.5 及其託管語言的一組擴充套件,它將查詢設定為物件。它定義了一種通用的語法和程式設計模型,可以使用通用的語言查詢不同型別的資料。

.NET Framework 3.5 中的 LINQ 和 C# 和 VB 編譯器實現了諸如 Select、Project、Join、Group、Partition、Set 等關係運算符,這些運算子支援 LINQ 語法,可以無需藉助 ADO.NET 來處理配置好的資料儲存。

例如,使用 C# 中的 LINQ 查詢查詢 Northwind 資料庫中的 Customers 表,程式碼如下:

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 查詢返回標題。

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 Result

上面的 LINQ 表示式

var booktitles = 
from b in books 
select b.Title;

等效於以下 SQL 查詢:

SELECT Title from Books

LINQ 運算子

除了到目前為止使用的運算子外,還有其他一些運算子實現了所有查詢子句。讓我們來看一些運算子和子句。

Join 子句

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_Load 事件處理程式中新增程式碼,以使用 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);
}

生成的頁面如下所示:

LINQ Result2

Where 子句

“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 的那些行。

LINQ Result3

Orderby 和 Orderbydescending 子句

這些子句允許對查詢結果進行排序。要按價格對書籍的標題、頁數和價格進行排序,請在 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};

返回的元組如下:

LINQ Result4

Let 子句

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};

生成的查詢頁面如下所示:

LINQ Result5
廣告