Entity Framework 4.0 と ObjectDataSource コントロールの使用(パート 3: 並べ替えとフィルター処理)

作成者: Tom Dykstra

このチュートリアル シリーズは、Entity Framework 4.0 チュートリアル シリーズを使用してはじめにによって作成された Contoso University Web アプリケーションに基づいています。 以前のチュートリアルを完了していない場合は、このチュートリアルの開始点として、作成 したアプリケーションをダウンロード できます。 完全なチュートリアル シリーズによって作成された アプリケーションをダウンロード することもできます。 チュートリアルについて質問がある場合は、 ASP.NET Entity Framework フォーラムに投稿できます。

前のチュートリアルでは、Entity Framework と コントロールを使用する n 層 Web アプリケーションにリポジトリ パターンを ObjectDataSource 実装しました。 このチュートリアルでは、並べ替えとフィルター処理を行い、マスター詳細シナリオを処理する方法について説明します。 Departments.aspx ページに次の機能強化を追加します。

  • ユーザーが名前で部門を選択できるようにするテキスト ボックス。
  • グリッドに表示される各部門のコースの一覧。
  • 列見出しをクリックして並べ替える機能。

機能強化の準備ができている [部門] ページを示すスクリーンショット。

GridView 列を並べ替える機能の追加

Departments.aspx ページを開き、 という名前DepartmentsObjectDataSourceSortParameterName="sortExpression"コントロールに属性をObjectDataSource追加します。 (後で という名前sortExpressionのパラメーターをGetDepartments受け取るメソッドを作成します)。コントロールの開始タグのマークアップは、次の例のようになります。

<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 で、 メソッドからコントロールの メソッドをGridView呼び出して、既定のSort並べ替え順序をPage_Load設定します。

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

ビジネス ロジック クラスまたはリポジトリ クラスで並べ替えまたはフィルター処理を行うコードを追加できます。 ビジネス ロジック クラスで行うと、ビジネス ロジック クラスがリポジトリから返されたオブジェクトを操作しているため、データがデータベースから取得された後に並べ替えまたはフィルター処理 IEnumerable が行われます。 リポジトリ クラスに並べ替えコードとフィルター 処理コードを追加し、LINQ 式またはオブジェクト クエリがオブジェクトに IEnumerable 変換される前に行うと、コマンドは処理のためにデータベースに渡されます。これは通常、より効率的です。 このチュートリアルでは、並べ替えとフィルター処理を実装します。これにより、データベース (つまり、リポジトリ) によって処理が実行されます。

並べ替え機能を追加するには、リポジトリ インターフェイスとリポジトリ クラス、およびビジネス ロジック クラスに新しいメソッドを追加する必要があります。 ISchoolRepository.cs ファイルで、返される部門の一覧を並べ替えるために使用されるパラメーターをsortExpression受け取る新しいGetDepartmentsメソッドを追加します。

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

このコードでは、sort パラメーターをリポジトリ メソッドに渡します。

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" />

という名前DepartmentsObjectDataSourceObjectDataSourceコントロールで、次の操作を行います。

  • コントロールに SelectParameters 入力された値を取得する という名前 nameSearchString のパラメーターの要素を SearchTextBox 追加します。
  • 属性値を SelectMethodGetDepartmentsByName変更します。 (このメソッドは後で作成します)。

コントロールの 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 で、 パラメーターと nameSearchString パラメーターの両方sortExpressionGetDepartmentsByName受け取るメソッドを追加します。

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 使用して、検索文字列を含む項目を選択します。 検索文字列が空の場合は、すべてのレコードが選択されます。 次のような 1 つのステートメントでメソッド呼び出しを一緒に指定する場合 (Includeその後 OrderBy、、) Where、メソッドは Where 常に最後である必要があることに注意してください。

パラメーターを受け取る既存 GetDepartments のメソッドを sortExpression 変更して、新しいメソッドを呼び出します。

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 コントロールを使用し、エンティティのナビゲーション プロパティの Courses データにデータを Department バインドします。

Departments.aspx を開き、コントロールのGridViewマークアップで イベントのハンドラーをRowDataBound指定します。 コントロールの開始タグのマークアップは、次の例のようになります。

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

テンプレート フィールドの後に新しい TemplateField 要素を Administrator 追加します。

<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 し、ナビゲーション プロパティを Courses コレクションに List 変換し、入れ子になった GridView をコレクションにデータバインドします。

SchoolRepository.cs ファイルを開き、 メソッドで作成GetDepartmentsByNameしたオブジェクト クエリで メソッドをIncludeCourses呼び出して、ナビゲーション プロパティの一括読み込みを指定します。 メソッドの GetDepartmentsByName ステートメントはreturn、次の例のようになります。

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

ページを実行します。 前に追加した並べ替えとフィルター処理の機能に加えて、GridView コントロールに各部門の入れ子になったコースの詳細が表示されるようになりました。

入れ子になったコースの詳細を表示するグリッド ビュー コントロールを示すスクリーンショット。

これで、並べ替え、フィルター処理、マスター詳細のシナリオの概要が完了します。 次のチュートリアルでは、コンカレンシーを処理する方法について説明します。