使用 Entity Framework 4.0 和 ObjectDataSource 控制項,第 3 部分:排序和篩選

By Tom Dykstra

本教學課程系列是以 Contoso University Web 應用程式為基礎,此應用程式是由使用 Entity Framework 4.0教學課程系列消費者入門所建立。 如果您未完成先前的教學課程,作為本教學課程的起點,您可以下載您已建立 的應用程式 。 您也可以下載完整教學課程系列所建立 的應用程式 。 如果您有有關教學課程的問題,您可以將這些教學課程張貼至 ASP.NET Entity Framework 論壇

在上一個教學課程中,您在使用 Entity Framework 和 ObjectDataSource 控制項的多層式 Web 應用程式中實作存放庫模式。 本教學課程說明如何進行排序和篩選,以及處理主要詳細資料案例。 您會將下列增強功能新增至 Departments.aspx 頁面:

  • 文字方塊,允許使用者依名稱選取部門。
  • 方格中顯示的每個部門課程清單。
  • 按一下資料行標題來排序的能力。

顯示 [部門] 頁面可供增強功能的螢幕擷取畫面。

新增排序 GridView 資料行的功能

開啟 Departments.aspx 頁面,並將屬性新增 SortParameterName="sortExpression" 至名為 的 ObjectDataSourceDepartmentsObjectDataSource 控制項。 (稍後,您將建立一個 GetDepartments 方法,其採用名為 sortExpression .) 控制項開頭標記的標記現在類似下列範例。

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.BLL.SchoolBL" DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" DeleteMethod="DeleteDepartment" UpdateMethod="UpdateDepartment"
        ConflictDetection="CompareAllValues" OldValuesParameterFormatString="orig{0}" 
        OnUpdated="DepartmentsObjectDataSource_Updated" SortParameterName="sortExpression" >

AllowSorting="true" 屬性新增至控制項的 GridView 開頭標記。 控制項開頭標記的標記現在類似下列範例。

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" 
        OnRowUpdating="DepartmentsGridView_RowUpdating"
        AllowSorting="true" >

Departments.aspx.cs中,從 Page_Load 方法呼叫 GridView 控制項 Sort 的 方法,以設定預設排序次序:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        DepartmentsGridView.Sort("Name", SortDirection.Ascending);
    }
}

您可以在商務邏輯類別或存放庫類別中新增排序或篩選的程式碼。 如果您在商務邏輯類別中執行此動作,排序或篩選工作會在從資料庫擷取資料之後完成,因為商務邏輯類別正在使用 IEnumerable 存放庫傳回的物件。 如果您在存放庫類別中新增排序和篩選程式代碼,並在 LINQ 運算式或物件查詢轉換成 IEnumerable 物件之前執行此動作,您的命令將會傳遞至資料庫進行處理,這通常是更有效率的。 在本教學課程中,您將以導致資料庫完成處理的方式實作排序和篩選,也就是存放庫中的 。

若要新增排序功能,您必須將新方法新增至存放庫介面和存放庫類別,以及新增至商務邏輯類別。 在 ISchoolRepository.cs 檔案中,新增 GetDepartments 方法,其會採用 sortExpression 將用來排序所傳回部門清單的參數:

IEnumerable<Department> GetDepartments(string sortExpression);

參數 sortExpression 會指定要排序的資料行和排序方向。

將新方法的程式碼新增至 SchoolRepository.cs 檔案:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    if (String.IsNullOrWhiteSpace(sortExpression))
    {
        sortExpression = "Name";
    }
    return context.Departments.Include("Person").OrderBy("it." + sortExpression).ToList();
}

變更現有的無 GetDepartments 參數方法以呼叫新的方法:

public IEnumerable<Department> GetDepartments()
{
    return GetDepartments("");
}

在測試專案中,將下列新方法新增至 MockSchoolRepository.cs

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return departments;
}

如果您要建立任何相依于此方法傳回已排序清單的單元測試,您必須先排序清單,再傳回清單。 您不會在此教學課程中建立類似的測試,因此方法只能傳回未排序的部門清單。

SchoolBL.cs 檔案中,將下列新方法新增至商務邏輯類別:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return schoolRepository.GetDepartments(sortExpression);
}

此程式碼會將排序參數傳遞至存放庫方法。

執行 Departments.aspx 頁面。

Image02

您現在可以按一下任何資料行標題,依該資料行排序。 如果資料行已經排序,請按一下標題會反轉排序方向。

在本節中,您將新增搜尋文字方塊、使用控制項參數將它連結至 ObjectDataSource 控制項,並將方法新增至商務邏輯類別以支援篩選。

開啟 Departments.aspx 頁面,並在標題與第一個 ObjectDataSource 控制項之間新增下列標記:

Enter any part of the name or leave the box blank to see all names:
    <asp:TextBox ID="SearchTextBox" runat="server" AutoPostBack="true"></asp:TextBox>
     <asp:Button ID="SearchButton" runat="server" Text="Search" />

在名為 DepartmentsObjectDataSource 的 控制項中 ObjectDataSource ,執行下列動作:

  • SelectParameters為名為 nameSearchString 的參數新增專案,以取得控制項中 SearchTextBox 輸入的值。
  • SelectMethod 屬性值變更為 GetDepartmentsByName 。 (您稍後會建立此方法。)

控制項的 ObjectDataSource 標記現在類似下列範例:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" TypeName="ContosoUniversity.BLL.SchoolBL"
        SelectMethod="GetDepartmentsByName" DeleteMethod="DeleteDepartment" UpdateMethod="UpdateDepartment"
        DataObjectTypeName="ContosoUniversity.DAL.Department" ConflictDetection="CompareAllValues"
        SortParameterName="sortExpression" OldValuesParameterFormatString="orig{0}" 
        OnUpdated="DepartmentsObjectDataSource_Updated">
        <SelectParameters>
            <asp:ControlParameter ControlID="SearchTextBox" Name="nameSearchString" PropertyName="Text"
                Type="String" />
        </SelectParameters>
    </asp:ObjectDataSource>

ISchoolRepository.cs中,新增 GetDepartmentsByName 接受 sortExpressionnameSearchString 參數的方法:

IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString);

SchoolRepository.cs中,新增下列新方法:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    if (String.IsNullOrWhiteSpace(sortExpression))
    {
        sortExpression = "Name";
    }
    if (String.IsNullOrWhiteSpace(nameSearchString))
    {
        nameSearchString = "";
    }
    return context.Departments.Include("Person").OrderBy("it." + sortExpression).Where(d => d.Name.Contains(nameSearchString)).ToList();
}

此程式碼會使用 Where 方法來選取包含搜尋字串的專案。 如果搜尋字串是空的,則會選取所有記錄。 請注意,當您在一個語句中指定方法呼叫時,例如, (Include ,然後 OrderByWhere) , Where 方法一律必須是最後一個。

變更採用 sortExpression 參數來呼叫新方法的現有 GetDepartments 方法:

public IEnumerable<Department> GetDepartments(string sortExpression)
{
    return GetDepartmentsByName(sortExpression, "");
}

在測試專案中的 MockSchoolRepository.cs 中,新增下列新方法:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    return departments;
}

SchoolBL.cs中,新增下列新方法:

public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
    return schoolRepository.GetDepartmentsByName(sortExpression, nameSearchString);
}

執行 Departments.aspx 頁面並輸入搜尋字串,以確定選取邏輯正常運作。 將文字方塊保留空白,並嘗試搜尋以確定傳回所有記錄。

Image03

為每個方格資料列新增詳細資料行

接下來,您想要查看方格右側儲存格中顯示的每個部門的所有課程。 若要這樣做,您將使用巢狀 GridView 控制項,並將它系結至實體導覽屬性 Department 中的資料 Courses

開啟 Departments.aspx ,並在 控制項的 GridView 標記中指定 事件的處理常式 RowDataBound 。 控制項開頭標記的標記現在類似下列範例。

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" 
        OnRowUpdating="DepartmentsGridView_RowUpdating"
        OnRowDataBound="DepartmentsGridView_RowDataBound"
        AllowSorting="True" >

在範本欄位後面 Administrator 新增專案 TemplateField

<asp:TemplateField HeaderText="Courses">
                <ItemTemplate>
                    <asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False">
                        <Columns>
                            <asp:BoundField DataField="CourseID" HeaderText="ID" />
                            <asp:BoundField DataField="Title" HeaderText="Title" />
                        </Columns>
                    </asp:GridView>
                </ItemTemplate>
            </asp:TemplateField>

此標記會建立巢狀 GridView 控制項,以顯示課程清單的課程編號和標題。 它不會指定資料來源,因為您將資料系結在處理常式中的程式碼中 RowDataBound

開啟 Departments.aspx.cs ,並新增 RowDataBound 事件的下列處理常式:

protected void DepartmentsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var department = e.Row.DataItem as Department;
        var coursesGridView = (GridView)e.Row.FindControl("CoursesGridView");
        coursesGridView.DataSource = department.Courses.ToList();
        coursesGridView.DataBind();
    }
}

此程式碼會從事件引數取得 Department 實體、將導覽屬性 List 轉換成 Courses 集合,並將巢狀 GridView 系結至集合的資料系結。

開啟SchoolRepository.cs檔案, Courses 並在您在 方法中 GetDepartmentsByName 建立的物件查詢中呼叫 Include 方法,以指定導覽屬性的積極式載入。 return方法中的 GetDepartmentsByName 語句現在類似下列範例。

return context.Departments.Include("Person").Include("Courses").
    OrderBy("it." + sortExpression).Where(d => d.Name.Contains(nameSearchString)).ToList();

執行頁面。 除了您稍早新增的排序和篩選功能之外,GridView 控制項現在還會顯示每個部門的巢狀課程詳細資料。

顯示顯示巢狀課程詳細資料之方格檢視控制項的螢幕擷取畫面。

這會完成排序、篩選和主要詳細資料案例的簡介。 在下一個教學課程中,您將瞭解如何處理平行存取。