[VS2010] ASP.NET 4.0 在資料存取以及資料控制項上的增強
ASP.NET 4.0 可以算是自從 2.0 開始以來最大幅度的改版,不論是 Web Forms,MVC,AJAX 還是核心服務 (Core Service),都做了不小的改變,為了因應在這幾年來瞬息萬變的 Web 應用程式技術與開發功能,像是 jQuery 這種 Framework 也是近幾年發展出來的,CSS 和跨瀏覽器的需求也是在第二次瀏覽器大戰延燒之下所產生的,而 ASP.NET 2.0 的核心在這段激烈的攻防戰中早已露出疲態,也刺激了 ASP.NET 團隊對核心部份做出大多數的改變,在前篇文章所提到的 Menu 的 semantically markup 和 FormView 更乾淨的 HTML 輸出就是很好的例子,當然 ASP.NET 4.0 的改變不只有那些而已,基於 .NET Framework 3.5 的 LINQ 以及 ADO.NET Entity Framework 的發展,在 ASP.NET 中也導入了一些延伸性的支援,本文所要介紹的就是兩個 ASP.NET 4.0 在資料存取與控制這部份的強化。
1. QueryExtender 讓基於 LINQ 的查詢更具擴充性。
自從 LINQ 於 .NET Framework 3.5 發表出來以後,在 C# 社群引起來非常大的震憾,因為它將存取物件集合的方式以類似於 SQL 指令的方式處理,LINQ to SQL 以及 Entity Framework 的 LINQ to Entities 更將範圍延伸到資料庫存取上,各式各樣的 LINQ Query Provider 也如同雨後春筍般發展起來,像是 LINQ to Active Directory, LINQ to Oracle 或 LINQ to Wikipedia 等等,似乎只要是可以用集合物件表示的資料,都可以用 LINQ 來查詢,只是這項褔利在 LinqDataSource 和 EntityDataSource 中似乎有一點侷限,雖然這兩個 Data Source Control 都有 Where 的屬性可以用,但是彈性就是不怎麼好,因為那是一個寫死的字串。
<asp:DropDownList AutoPostBack="true" ID="DropDownList1" runat="server">
<asp:ListItem Value="0"></asp:ListItem>
<asp:ListItem Value="25"></asp:ListItem>
<asp:ListItem Value="100"></asp:ListItem>
<asp:ListItem Value="400"></asp:ListItem>
</asp:DropDownList>
<asp:LinqDataSource
ContextTypeName="ExampleDataContext"
TableName="Products"
Where="Price>@UserPrice"
ID="LinqDataSource1"
runat="server">
<WhereParameters>
<asp:ControlParameter
Name="UserPrice"
DefaultValue="0"
ControlID="DropDownList1"
Type="Int32" />
</WhereParameters>
</asp:LinqDataSource>
<asp:GridView
DataSourceID="LinqDataSource1"
ID="GridView1"
runat="server">
</asp:GridView>
大家也都知道,像這種資料查詢的參數最好是多一點動態以及更寬廣的條件設定,甚至是排序的條件等,但 LinqDataSource 以及 EntityDataSource 在這個功能上受到了不少的限制,因此 ASP.NET 4.0 為了這兩個控制項開發了一個可以再延伸查詢功能的元件,稱為 QueryExtender (查詢延伸器),QueryExtender 可以在現有的 Data Source 上面加上查詢的過濾以及排序陳述,以在查詢結果中處理條件的篩選功能。像是範圍篩選 (RangeExpression),屬性篩選 (PropertyExpression),排序篩選 (OrderByExpression),選取篩選 (SearchExpression) 以及自訂的篩選器 (CustomExpression) 等,它可以達到以宣告式 (Declarative) 的方式來設定額外的查詢條件,因此對於 LinqDataSource 以及 EntityDataSource 的使用者是個大利多。
下表是 QueryExtender 所支援的查詢過濾器:
下列的程式碼是使用 QueryExtender 強化查詢選項的範例:
<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="DataClassesDataContext" EntityTypeName="" Select="new (HomeID, Bedrooms, ImageURL, Price, Available, Description)" TableName="Homes"> </asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1" TargetControlID="LinqDataSource1" runat="server"> <asp:OrderByExpression DataField="Price" Direction="Descending"></asp:OrderByExpression> <!-- 排序 --> <asp:RangeExpression DataField="Price" MinType="Inclusive" MaxType="Inclusive"><!-- 範圍設定 --> <asp:Parameter DefaultValue="200000" DbType="Int32" /> <asp:Parameter DefaultValue="750000" DbType="Int32" /> </asp:RangeExpression> <asp:PropertyExpression><!-- 設定指定屬性做過濾 --> <asp:Parameter Name="Available" DefaultValue="True" DbType="Boolean" /> </asp:PropertyExpression> <asp:SearchExpression DataFields="Description" SearchType="Contains"><!-- 檢查欄位中的資料 --> <asp:Parameter DefaultValue="private" DbType="String" /> </asp:SearchExpression> </asp:QueryExtender>
上面的 QueryExtender 指令會產出下列的 SQL 指令 (配合 Entity Framework Data Source 時):
exec sp_executesql N'SELECT [t0].[HomeID], [t0].[Bedrooms], [t0].[ImageURL], [t0].[Price], [t0].[Available], [t0].[Description] FROM [dbo].[Homes] AS [t0] WHERE ([t0].[Description] LIKE @p0) AND ([t0].[Available] = @p1) AND ([t0].[Price] >= @p2) AND ([t0].[Price] <= @p3) ORDER BY [t0].[Price] DESC', N'@p0 nvarchar(4000),@p1 int,@p2 int,@p3 int', @p0=N'%private%', @p1=1, @p2=200000, @p3=750000
QueryExtender 除了可以支援 LinqDataSource 以及 EntityDataSource 外,它也可以和其他第三方軟體開發商的 Data Source 控制項合併使用。
2. EnablePersistedSelection 讓已選取的選項不會因為分頁而移動
以往如果在 GridView 以及 ListView 控制項中,如果有做分頁的話,若選擇其中一筆資料時,控制項會以當下的 ROW INDEX 來保存哪一列被選取,但是它不會受到翻頁的影響,也就是說就算是翻項了,該 ROW INDEX 的選取狀態會仍然存在,如同下圖的變化:
這會讓開發人員還要額外處理選取狀態的變化,否則選取的資料列就會不正確,這個問題似乎可以說是一種 bug,但到了 ASP.NET 4.0,這個問題已經解決,在 ASP.NET 4.0 的 GridView 和 ListView 中,新增了一個 EnablePersistedSelection 屬性,它可以讓 GridView 和 ListView 以資料鍵值 (data-key value) 來保持選取的狀態,因此到了 ASP.NET 4.0,上列的圖會變成這樣:
可以看到,ListView 的列選取狀態不會再像原本那樣被列索引鎖死,而是以資料鍵值來維持。
參考資料:
ASP.NET 4.0 Query Extender
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.queryextender(VS.100).aspx