Share via


Entity Framework 4.0 및 ObjectDataSource 컨트롤 사용, 3부: 정렬 및 필터링

작성자: Tom Dykstra

이 자습서 시리즈는 Entity Framework 4.0 자습서 시리즈를 사용하여 시작 만든 Contoso University 웹 애플리케이션을 기반으로 합니다. 이전 자습서를 완료하지 않은 경우 이 자습서의 시작점으로 만든 애플리케이션을 다운로드 할 수 있습니다. 전체 자습서 시리즈에서 만든 애플리케이션을 다운로드 할 수도 있습니다. 자습서에 대한 질문이 있는 경우 ASP.NET Entity Framework 포럼에 게시할 수 있습니다.

이전 자습서에서는 Entity Framework 및 컨트롤을 사용하는 n 계층 웹 애플리케이션에서 리포지토리 패턴을 구현했습니다 ObjectDataSource . 이 자습서에서는 정렬 및 필터링을 수행하고 master 세부 시나리오를 처리하는 방법을 보여 줍니다. Departments.aspx 페이지에 다음과 같은 향상된 기능을 추가합니다.

  • 사용자가 이름으로 부서를 선택할 수 있도록 하는 텍스트 상자입니다.
  • 표에 표시된 각 부서의 과정 목록입니다.
  • 열 머리글을 클릭하여 정렬하는 기능입니다.

향상된 기능을 사용할 수 있는 부서 페이지를 보여 주는 스크린샷

GridView 열을 정렬하는 기능 추가

Departments.aspx 페이지를 열고 라는 DepartmentsObjectDataSource컨트롤에 ObjectDataSource 특성을 추가 SortParameterName="sortExpression" 합니다. (나중에 라는 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에서 메서드에서 컨트롤의 Sort 메서드를 GridView 호출하여 기본 정렬 순서를 Page_Load 설정합니다.

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

비즈니스 논리 클래스 또는 리포지토리 클래스에서 정렬하거나 필터링하는 코드를 추가할 수 있습니다. 비즈니스 논리 클래스에서 수행하는 경우 비즈니스 논리 클래스가 리포지토리에서 반환된 개체로 IEnumerable 작업하기 때문에 데이터베이스에서 데이터를 검색한 후 정렬 또는 필터링 작업이 수행됩니다. 리포지토리 클래스에 정렬 및 필터링 코드를 추가하고 LINQ 식 또는 개체 쿼리가 개체로 변환 IEnumerable 되기 전에 이 작업을 수행하는 경우 일반적으로 더 효율적인 처리를 위해 명령이 데이터베이스로 전달됩니다. 이 자습서에서는 데이터베이스, 즉 리포지토리에서 처리를 수행하는 방식으로 정렬 및 필터링을 구현합니다.

정렬 기능을 추가하려면 비즈니스 논리 클래스뿐만 아니라 리포지토리 인터페이스 및 리포지토리 클래스에 새 메서드를 추가해야 합니다. ISchoolRepository.cs 파일에서 반환되는 부서 목록을 정렬하는 데 사용할 매개 변수를 사용하는 sortExpressionGetDepartments 메서드를 추가합니다.

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

라는 DepartmentsObjectDataSource컨트롤에서 ObjectDataSource 다음을 수행합니다.

  • 컨트롤에 입력된 SelectParametersSearchTextBox 값을 가져오는 라는 nameSearchString 매개 변수에 대한 요소를 추가합니다.
  • 특성 값을 로 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에서 및 nameSearchString 매개 변수를 GetDepartmentsByName 모두 sortExpression 사용하는 메서드를 추가합니다.

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다음 OrderBy, ) Where메서드는 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" >

템플릿 필드 다음에 AdministratorTemplateField 요소를 추가합니다.

<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 를 databinds합니다.

SchoolRepository.cs 파일을 열고 메서드에서 만든 개체 쿼리에서 메서드를 호출 Include 하여 탐색 속성에 대한 Courses 즉시 로드를 GetDepartmentsByName 지정합니다. 이제 메서드의 GetDepartmentsByName 문은 return 다음 예제와 유사합니다.

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

페이지를 실행합니다. 이전에 추가한 정렬 및 필터링 기능 외에도 GridView 컨트롤에는 이제 각 부서에 대한 중첩된 과정 세부 정보가 표시됩니다.

중첩된 과정 세부 정보를 표시하는 그리드 보기 컨트롤을 보여 주는 스크린샷

이렇게 하면 정렬, 필터링 및 master 세부 시나리오에 대한 소개가 완료됩니다. 다음 자습서에서는 동시성을 처리하는 방법을 알아보세요.