消費者入門 Entity Framework 4.0 Database First 和 ASP.NET 4 Web Form - 第 3 部分

By Tom Dykstra

Contoso University 範例 Web 應用程式示範如何使用 Entity Framework 4.0 和 Visual Studio 2010 建立 ASP.NET Web Forms應用程式。 如需教學課程系列的相關資訊,請參閱 系列中的第一個教學課程

篩選、排序和分組資料

在上一個教學課程中, EntityDataSource 您已使用 控制項來顯示和編輯資料。 在本教學課程中,您將篩選、排序和群組資料。 當您藉由設定控制項的屬性 EntityDataSource 來執行此動作時,語法與其他資料來源控制項不同。 不過,如您所見,您可以使用 QueryExtender 控制項將這些差異降至最低。

您將變更 Students.aspx 頁面來篩選學生、依名稱排序,以及搜尋名稱。 您也會變更 Courses.aspx 頁面,以顯示所選部門的課程,並依名稱搜尋課程。 最後,您會將學生統計資料新增至 About.aspx 頁面。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示學生清單檢視與學生表格。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [依部門排序的課程] 和 [依名稱排序的課程] 檢視。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [學生主體統計資料] 檢視,其中包含註冊日期的資料表。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [依名稱尋找學生] 檢視,其中已輸入搜尋查詢中的字母 g。

使用 EntityDataSource 「Where」 屬性來篩選資料

開啟您在上一個教學課程中建立的 Students.aspx 頁面。 如目前設定, GridView 頁面中的控制項會顯示實體集中的所有名稱 People 。 不過,您想要只顯示學生,您可以藉由選取 Person 具有非 Null 註冊日期的實體來找到。

切換至 [設計] 檢視,然後選取 EntityDataSource 控制項。 在 [屬性] 視窗中,將 Where 屬性設定為 it.EnrollmentDate is not null

Image01

您在 控制項的 EntityDataSource 屬性中使用的 Where 語法為 Entity SQL。 Entity SQL 類似于 Transact-SQL,但它已自訂來搭配實體使用,而不是資料庫物件。 在運算式 it.EnrollmentDate is not null 中,這個字 it 代表查詢所傳回之實體的參考。 因此, it.EnrollmentDate 參考 EnrollmentDate 控制項傳回之 Person 實體 EntityDataSource 的 屬性。

執行頁面。 學生清單現在只包含學生。 (沒有註冊日期時,不會顯示任何資料列。)

Internet Explorer 視窗的螢幕擷取畫面,其中顯示學生清單檢視與學生資料表。

使用 EntityDataSource 「OrderBy」 屬性來排序資料

當您第一次顯示此清單時,您也會希望此清單依名稱順序排列。 當 Students.aspx 頁面仍然在 [設計 ] 檢視中開啟,而且 EntityDataSource 在 [ 屬性 ] 視窗中,將 OrderBy 屬性設定為 it.LastName

Image05

執行頁面。 學生清單現在依姓氏排列順序。

Image04

使用控制項參數來設定 「Where」 屬性

如同其他資料來源控制項,您可以將參數值傳遞至 Where 屬性。 在您在教學課程的第 2 部分中建立 的 Courses.aspx 頁面上,您可以使用這個方法來顯示與使用者從下拉式清單中選取的部門相關聯的課程。

開啟 Courses.aspx ,並切換至 [設計] 檢視。 將第二 EntityDataSource 個控制項新增至頁面,並將它命名為 CoursesEntityDataSource 。 將它連接到 SchoolEntities 模型,然後選取 Courses 作為 EntitySetName 值。

在 [ 屬性 ] 視窗中,按一下 [Where ] 屬性方塊中的省略號。 (使用 [屬性] 視窗之前,請確定 CoursesEntityDataSource 仍選取控制項。)

Image06

[ 運算式編輯器 ] 對話方塊隨即顯示。 在此對話方塊中,選取 [ 根據提供的參數自動產生 Where 運算式],然後按一下 [ 新增參數]。 將參數命名為 ,選取[控制項] 作為[DepartmentID 參數來源值],然後選取[DepartmentsDropDownList] 作為ControlID值。

Image07

按一下[顯示進階屬性],然後在 [運算式編輯器] 對話方塊的 [屬性] 視窗中,將 Type 屬性變更為 Int32

Image15

完成後,請按一下 [確定]。

在下拉式清單下方,將控制項新增 GridView 至頁面,並將它命名為 CoursesGridView 。 將它連接到 CoursesEntityDataSource 資料來源控制項,按一下 [ 重新整理架構]、按一下 [ 編輯資料行],然後移除資料 DepartmentID 行。 控制項 GridView 標記類似下列範例。

<asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="CourseID" DataSourceID="CoursesEntityDataSource">
        <Columns>
            <asp:BoundField DataField="CourseID" HeaderText="ID" ReadOnly="True" 
                SortExpression="CourseID" />
            <asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" 
                SortExpression="Credits" />
        </Columns>
    </asp:GridView>

當使用者在下拉式清單中變更選取的部門時,您希望相關聯的課程清單自動變更。 若要這樣做,請選取下拉式清單,然後在 [ 屬性 ] 視窗中將 AutoPostBack 屬性設定為 True

Image08

現在您已使用設計工具完成,請切換至[來源] 檢視,並將 控制項的 CoursesEntityDataSourceDefaultContainer 名稱屬性取代 ConnectionStringContextTypeName="ContosoUniversity.DAL.SchoolEntities" 屬性。 完成時,控制項的標記看起來會像下列範例一樣。

<asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false"
        EntitySetName="Courses" 
        AutoGenerateWhereClause="true" Where="">
        <WhereParameters>
            <asp:ControlParameter ControlID="DepartmentsDropDownList" Type="Int32" 
                Name="DepartmentID" PropertyName="SelectedValue" />
        </WhereParameters>
    </asp:EntityDataSource>

執行頁面並使用下拉式清單來選取不同的部門。 只有所選部門所提供的課程會顯示在 控制項中 GridView

Image09

使用 EntityDataSource 「GroupBy」 屬性來群組資料

假設 Contoso University 想要在其 [關於] 頁面上放置一些學生主體統計資料。 具體而言,其想要依註冊日期顯示學生數目的明細。

開啟 About.aspx,然後在 [來源 ] 檢視中,將控制項的現有內容 BodyContent 取代為標記之間的 h2 「學生本文統計資料」:

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>Student Body Statistics</h2>
</asp:Content>

標題之後,新增 EntityDataSource 控制項並將其命名為 StudentStatisticsEntityDataSource 。 將它連線至 SchoolEntities ,選取實體集,並將精靈中的 [ People選取 ] 方塊保留不變。 在 [ 屬性 ] 視窗中設定下列屬性:

  • 若要僅篩選學生,請將 Where 屬性設定為 it.EnrollmentDate is not null
  • 若要依註冊日期將結果分組,請將 GroupBy 屬性設定為 it.EnrollmentDate
  • 若要選取註冊日期和學生數目,請將 Select 屬性設定為 it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents
  • 若要依註冊日期排序結果,請將 OrderBy 屬性設定為 it.EnrollmentDate

[來源 ] 檢視中,以 ConnectionString 屬性取代 和 DefaultContainer 名稱屬性 ContextTypeName 。 控制項 EntityDataSource 標記現在類似于下列範例。

<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents" 
        OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate"
        Where="it.EnrollmentDate is not null" >
    </asp:EntityDataSource>

、 和 屬性的 Select 語法類似于 Transact-SQL,但指定目前實體的關鍵字除外 itWhereGroupBy

新增下列標記以建立 GridView 控制項以顯示資料。

<asp:GridView ID="StudentStatisticsGridView" runat="server" AutoGenerateColumns="False" 
        DataSourceID="StudentStatisticsEntityDataSource">
        <Columns>
            <asp:BoundField DataField="EnrollmentDate" DataFormatString="{0:d}" 
                HeaderText="Date of Enrollment" 
                ReadOnly="True" SortExpression="EnrollmentDate" />
            <asp:BoundField DataField="NumberOfStudents" HeaderText="Students" 
                ReadOnly="True" SortExpression="NumberOfStudents" />
        </Columns>
    </asp:GridView>

執行頁面以查看依註冊日期顯示學生數目的清單。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示具有註冊日期資料表的 Student Body Statistics 檢視。

使用 QueryExtender 控制項進行篩選和排序

QueryExtender控制項提供在標記中指定篩選和排序的方法。 語法與您正在使用的資料庫管理系統無關, (DBMS) 。 它通常與 Entity Framework 無關,但除了您用於導覽屬性的語法對 Entity Framework 而言是唯一的。

在本教學課程的這個部分中,您將使用 QueryExtender 控制項來篩選和排序資料,而其中一個排序依據欄位將會是導覽屬性。

(如果您想要使用程式碼而非標記來擴充控制項自動產生的 EntityDataSource 查詢,您可以藉由處理 QueryCreated 事件來執行此動作。這是控制項延伸 EntityDataSource 控制項查詢的方式 QueryExtender 。)

開啟 Courses.aspx 頁面,並在您先前新增的標記下方,插入下列標記以建立標題、輸入搜尋字串的文字方塊、搜尋按鈕,以及 EntityDataSource 系結至實體集的 Courses 控制項。

<h2>Courses by Name</h2>
    Enter a course name 
    <asp:TextBox ID="SearchTextBox" runat="server"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />
    <br /><br />
    <asp:EntityDataSource ID="SearchEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="Courses"  
        Include="Department" >
    </asp:EntityDataSource>

請注意,控制項 EntityDataSourceInclude 屬性設定為 Department 。 在資料庫中, Course 資料表不包含部門名稱;它包含 DepartmentID 外鍵資料行。 如果您直接查詢資料庫,若要取得部門名稱以及課程資料,則必須聯 Course 結 和 Department 資料表。 將 屬性設定 IncludeDepartment ,即可指定 Entity Framework 應該在取得 Course 實體時執行取得相關 Department 實體的工作。 Department實體接著會儲存在 Department 實體的 Course 導覽屬性中。 (根據預設, SchoolEntities 資料模型設計工具所產生的類別會在需要時擷取相關資料,而且您已將資料來源控制項系結至該類別,因此不需要設定 Include 屬性。不過,設定它可改善頁面的效能,因為 Entity Framework 會對資料庫進行個別呼叫,以擷取實體和相關 Department 實體的資料 Course 。)

在您剛建立的 EntityDataSource 控制項之後,插入下列標記來建立 QueryExtender 系結至該 EntityDataSource 控制項的控制項。

<asp:QueryExtender ID="SearchQueryExtender" runat="server" 
        TargetControlID="SearchEntityDataSource" >
        <asp:SearchExpression SearchType="StartsWith" DataFields="Title">
            <asp:ControlParameter ControlID="SearchTextBox" />
        </asp:SearchExpression>
        <asp:OrderByExpression DataField="Department.Name" Direction="Ascending">
            <asp:ThenBy DataField="Title" Direction="Ascending" />            
        </asp:OrderByExpression>
    </asp:QueryExtender>

元素 SearchExpression 會指定您想要選取標題符合文字方塊中輸入之值的課程。 只會比較文字方塊中輸入的字元數,因為 SearchType 屬性會 StartsWith 指定 。

元素 OrderByExpression 會指定結果集會依部門名稱內的課程標題排序。 請注意如何指定部門名稱: Department.Name 。 因為實體與 Department 實體之間的 Course 關聯是一對一, Department 所以導覽屬性會 Department 包含實體。 (如果這是一對多關聯性,屬性會包含 collection.) 若要取得部門名稱,您必須指定 Name 實體的屬性 Department

最後,新增 GridView 控制項以顯示課程清單:

<asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="CourseID" DataSourceID="SearchEntityDataSource"  AllowPaging="true">
        <Columns>
            <asp:TemplateField HeaderText="Department">
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Eval("Department.Name") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="CourseID" HeaderText="ID"/>
            <asp:BoundField DataField="Title" HeaderText="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" />
        </Columns>
    </asp:GridView>

第一個資料行是顯示部門名稱的範本欄位。 資料系結運算式會 Department.Name 指定 ,就像您在 控制項中看到 QueryExtender 一樣。

執行頁面。 初始顯示會顯示依部門排序的所有課程清單,然後依課程標題顯示。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [依部門排序的課程] 和 [依名稱排序的課程] 檢視。

輸入 「m」,然後按一下 [ 搜尋 ] 以查看標題開頭為 「m」 的所有課程, (搜尋不區分大小寫) 。

Image12

使用 「Like」 運算子來篩選資料

您可以使用 控制項屬性中的 WhereEntityDataSource 運算子,來達到類似 QueryExtender 控制項 StartsWith 的 、 ContainsEndsWith 搜尋類型 Like 的效果。 在本教學課程的這個部分中,您將瞭解如何使用 Like 運算子依名稱搜尋學生。

[來源] 檢視中開啟Students.aspx。 在 GridView 控制項之後,新增下列標記:

<h2>Find Students by Name</h2>
    Enter any part of the name
    <asp:TextBox ID="SearchTextBox" runat="server" AutoPostBack="true"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />
    <br />
    <br />
    <asp:EntityDataSource ID="SearchEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Where="it.EnrollmentDate is not null and (it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%')" >
        <WhereParameters>
            <asp:ControlParameter ControlID="SearchTextBox" Name="StudentName" PropertyName="Text" 
             Type="String" DefaultValue="%"/>
        </WhereParameters>
    </asp:EntityDataSource>
    <asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False" DataKeyNames="PersonID"
        DataSourceID="SearchEntityDataSource" AllowPaging="true">
        <Columns>
            <asp:TemplateField HeaderText="Name" SortExpression="LastName, FirstMidName">
                <ItemTemplate>
                    <asp:Label ID="LastNameFoundLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>, 
                    <asp:Label ID="FirstNameFoundLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
                <ItemTemplate>
                    <asp:Label ID="EnrollmentDateFoundLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

此標記類似于您稍早看到的內容, Where 但屬性值除外。 運算式的第二個部分 Where 會定義子字串搜尋 (LIKE %FirstMidName% or LIKE %LastName%) ,以搜尋文字方塊中輸入之任何專案的名字和姓氏。

執行頁面。 一開始您會看到所有學生,因為參數的 StudentName 預設值為 「%」。

Image13

在文字方塊中輸入字母 「g」,然後按一下 [ 搜尋]。 您會看到名字或姓氏中有 「g」 的學生清單。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [依名稱尋找學生] 檢視,其中輸入搜尋查詢中的字母 g。

您現在已從個別資料表顯示、更新、篩選、排序和分組資料。 在下一個教學課程中,您將開始處理 (主要詳細資料) 的相關資料。