Share via


Verwenden von Entity Framework 4.0 und dem ObjectDataSource-Steuerelement, Teil 3: Sortieren und Filtern

von Tom Dykstra

Diese Tutorialreihe baut auf der Contoso University-Webanwendung auf, die vom Erste Schritte mit der Tutorialreihe "Entity Framework 4.0" erstellt wird. Wenn Sie die vorherigen Tutorials nicht abgeschlossen haben, können Sie als Ausgangspunkt für dieses Tutorial die Anwendung herunterladen , die Sie erstellt hätten. Sie können auch die Anwendung herunterladen , die von der vollständigen Tutorialreihe erstellt wird. Wenn Sie Fragen zu den Tutorials haben, können Sie diese im ASP.NET Entity Framework-Forum posten.

Im vorherigen Tutorial haben Sie das Repositorymuster in einer n-Schicht-Webanwendung implementiert, die das Entity Framework und das ObjectDataSource Steuerelement verwendet. In diesem Tutorial erfahren Sie, wie Sie sortieren und filtern und master-Detailszenarien behandeln. Sie fügen der Seite Departments.aspx die folgenden Verbesserungen hinzu:

  • Ein Textfeld, mit dem Benutzer Abteilungen anhand des Namens auswählen können.
  • Eine Liste der Kurse für jede Abteilung, die im Raster angezeigt wird.
  • Die Möglichkeit zum Sortieren durch Klicken auf Spaltenüberschriften.

Screenshot: Seite

Hinzufügen der Möglichkeit zum Sortieren von GridView-Spalten

Öffnen Sie die Seite Departments.aspx , und fügen Sie dem Steuerelement ein SortParameterName="sortExpression" Attribut mit dem ObjectDataSource Namen DepartmentsObjectDataSourcehinzu. (Später erstellen Sie eine GetDepartments Methode, die einen Parameter namens sortExpressionakzeptiert.) Das Markup für das öffnende Tag des Steuerelements ähnelt nun dem folgenden Beispiel.

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

Fügen Sie das AllowSorting="true" Attribut dem öffnenden Tag des GridView Steuerelements hinzu. Das Markup für das öffnende Tag des Steuerelements ähnelt nun dem folgenden Beispiel.

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

Legen Sie in Departments.aspx.cs die Standardsortierreihenfolge fest, indem Sie die GridView -Methode des Steuerelements Sort aus der Page_Load -Methode aufrufen:

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

Sie können Code hinzufügen, der entweder in der Geschäftslogikklasse oder in der Repositoryklasse sortiert oder filtert. Wenn Sie dies in der Geschäftslogikklasse tun, erfolgt das Sortieren oder Filtern, nachdem die Daten aus der Datenbank abgerufen wurden, da die Geschäftslogikklasse mit einem IEnumerable objekt arbeitet, das vom Repository zurückgegeben wird. Wenn Sie der Repositoryklasse Sortier- und Filtercode hinzufügen und dies tun, bevor ein LINQ-Ausdruck oder eine Objektabfrage in ein IEnumerable Objekt konvertiert wurde, werden Ihre Befehle zur Verarbeitung an die Datenbank übergeben, was in der Regel effizienter ist. In diesem Tutorial implementieren Sie das Sortieren und Filtern so, dass die Verarbeitung durch die Datenbank erfolgt, d. h. im Repository.

Um die Sortierfunktion hinzuzufügen, müssen Sie der Repositoryschnittstelle und den Repositoryklassen sowie der Geschäftslogikklasse eine neue Methode hinzufügen. Fügen Sie in der Datei ISchoolRepository.cs eine neue GetDepartments Methode hinzu, die einen sortExpression Parameter akzeptiert, der zum Sortieren der Liste der zurückgegebenen Abteilungen verwendet wird:

IEnumerable<Department> GetDepartments(string sortExpression);

Der sortExpression Parameter gibt die zu sortierende Spalte und die Sortierrichtung an.

Fügen Sie der Datei SchoolRepository.cs Code für die neue Methode hinzu:

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

Ändern Sie die vorhandene parameterlose GetDepartments Methode, um die neue Methode aufzurufen:

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

Fügen Sie im Testprojekt die folgende neue Methode zu MockSchoolRepository.cs hinzu:

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

Wenn Sie Komponententests erstellen möchten, die von dieser Methode abhängen und eine sortierte Liste zurückgeben, müssen Sie die Liste sortieren, bevor Sie sie zurückgeben. In diesem Tutorial erstellen Sie keine Tests wie diese, sodass die Methode einfach die unsortierte Liste der Abteilungen zurückgeben kann.

Fügen Sie in der Datei SchoolBL.cs der Geschäftslogikklasse die folgende neue Methode hinzu:

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

Dieser Code übergibt den Sortierparameter an die Repositorymethode.

Führen Sie die Seite Departments.aspx aus .

Bild02

Sie können jetzt auf eine beliebige Spaltenüberschrift klicken, um nach dieser Spalte zu sortieren. Wenn die Spalte bereits sortiert ist, wird durch Klicken auf die Überschrift die Sortierrichtung umgekehrt.

In diesem Abschnitt fügen Sie ein Suchtextfeld hinzu, verknüpfen es mit dem ObjectDataSource Steuerelement mithilfe eines Steuerelementparameters und fügen der Geschäftslogikklasse eine Methode zur Unterstützung der Filterung hinzu.

Öffnen Sie die Seite Departments.aspx , und fügen Sie das folgende Markup zwischen der Überschrift und dem ersten ObjectDataSource Steuerelement hinzu:

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

Führen Sie im ObjectDataSource -Steuerelement mit dem Namen DepartmentsObjectDataSourcedie folgenden Schritte aus:

  • Fügen Sie ein SelectParameters Element für einen Parameter namens nameSearchString hinzu, der den in das Steuerelement eingegebenen SearchTextBox Wert abruft.
  • Ändern Sie den SelectMethod Attributwert in GetDepartmentsByName. (Sie erstellen diese Methode später.)

Das Markup für das ObjectDataSource Steuerelement ähnelt nun dem folgenden Beispiel:

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

Fügen Sie in ISchoolRepository.cs eine GetDepartmentsByName Methode hinzu, die sowohl parameter als auch sortExpressionnameSearchString akzeptiert:

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

Fügen Sie in SchoolRepository.cs die folgende neue Methode hinzu:

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

Dieser Code verwendet eine Where -Methode, um Elemente auszuwählen, die die Suchzeichenfolge enthalten. Wenn die Suchzeichenfolge leer ist, werden alle Datensätze ausgewählt. Beachten Sie, dass beim Angeben von Methodenaufrufen in einer Anweisung wie dieser (Include, dann OrderBy) Wheredie Where Methode immer die letzte sein muss.

Ändern Sie die vorhandene GetDepartments Methode, die einen sortExpression Parameter verwendet, um die neue Methode aufzurufen:

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

Fügen Sie in MockSchoolRepository.cs im Testprojekt die folgende neue Methode hinzu:

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

Fügen Sie in SchoolBL.cs die folgende neue Methode hinzu:

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

Führen Sie die Seite Departments.aspx aus , und geben Sie eine Suchzeichenfolge ein, um sicherzustellen, dass die Auswahllogik funktioniert. Lassen Sie das Textfeld leer, und versuchen Sie eine Suche, um sicherzustellen, dass alle Datensätze zurückgegeben werden.

Bild03

Hinzufügen einer Detailspalte für jede Rasterzeile

Als Nächstes möchten Sie alle Kurse für jede Abteilung anzeigen, die in der rechten Zelle des Rasters angezeigt werden. Dazu verwenden Sie ein geschachteltes GridView Steuerelement und binden es an Daten aus der Courses Navigationseigenschaft der Department Entität.

Öffnen Sie Departments.aspx , und geben Sie im Markup für das GridView Steuerelement einen Handler für das RowDataBound Ereignis an. Das Markup für das öffnende Tag des Steuerelements ähnelt nun dem folgenden Beispiel.

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

Fügen Sie nach dem Administrator Vorlagenfeld ein neues TemplateField Element hinzu:

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

Dieses Markup erstellt ein geschachteltes GridView Steuerelement, das die Kursnummer und den Titel einer Liste von Kursen anzeigt. Es wird keine Datenquelle angegeben, da Sie sie im Code des RowDataBound Handlers mit Daten binden.

Öffnen Sie Departments.aspx.cs , und fügen Sie den folgenden Handler für das RowDataBound Ereignis hinzu:

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

Dieser Code ruft die Department Entität aus den Ereignisargumenten ab, konvertiert die Courses Navigationseigenschaft in eine List Sammlung und bindet die geschachtelte GridView an die Auflistung.

Öffnen Sie die Datei SchoolRepository.cs , und geben Sie eager loading für die Courses Navigationseigenschaft an, indem Sie die Include -Methode in der Objektabfrage aufrufen, die Sie in der GetDepartmentsByName -Methode erstellen. Die return -Anweisung in der GetDepartmentsByName -Methode ähnelt nun dem folgenden Beispiel.

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

Führen Sie die Seite aus. Zusätzlich zu der Zuvor hinzugefügten Sortier- und Filterfunktion zeigt das GridView-Steuerelement jetzt geschachtelte Kursdetails für jede Abteilung an.

Screenshot des Rasteransicht-Steuerelements mit geschachtelten Kursdetails.

Dies schließt die Einführung in Sortier-, Filter- und master-Detailszenarien ab. Im nächsten Tutorial erfahren Sie, wie Sie die Parallelität behandeln.