Uso di Entity Framework 4.0 e del controllo ObjectDataSource, parte 3: ordinamento e filtro

di Tom Dykstra

Questa serie di esercitazioni si basa sull'applicazione Web Contoso University creata dalla Introduzione con la serie di esercitazioni di Entity Framework 4.0. Se non sono state completate le esercitazioni precedenti, come punto di partenza per questa esercitazione è possibile scaricare l'applicazione creata. È anche possibile scaricare l'applicazione creata dalla serie completa di esercitazioni. Se si hanno domande sulle esercitazioni, è possibile pubblicarli nel forum di Entity Framework ASP.NET.

Nell'esercitazione precedente è stato implementato il modello di repository in un'applicazione Web di livello n che usa Entity Framework e il ObjectDataSource controllo. Questa esercitazione illustra come eseguire l'ordinamento e il filtro e gestire scenari di dettaglio master. Si aggiungeranno i miglioramenti seguenti alla pagina Departments.aspx :

  • Casella di testo per consentire agli utenti di selezionare i reparti in base al nome.
  • Elenco di corsi per ogni reparto visualizzato nella griglia.
  • Possibilità di ordinare facendo clic su intestazioni di colonna.

Screenshot che mostra la pagina Reparti pronti per i miglioramenti.

Aggiunta della possibilità di ordinare le colonne gridView

Aprire la pagina Departments.aspx e aggiungere un SortParameterName="sortExpression" attributo al ObjectDataSource controllo denominato DepartmentsObjectDataSource. Successivamente si creerà un metodo che accetta un GetDepartments parametro denominato sortExpression.) Il markup per il tag di apertura del controllo ora è simile all'esempio seguente.

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

Aggiungere l'attributo AllowSorting="true" al tag di apertura del GridView controllo. Il markup per il tag di apertura del controllo ora è simile all'esempio seguente.

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

In Departments.aspx.cs impostare l'ordinamento predefinito chiamando il GridView metodo del Sort controllo dal Page_Load metodo:

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

È possibile aggiungere codice che ordina o filtra nella classe logica di business o nella classe repository. Se si esegue questa operazione nella classe della logica di business, il lavoro di ordinamento o filtro verrà eseguito dopo che i dati vengono recuperati dal database, perché la classe di logica di business lavora con un IEnumerable oggetto restituito dal repository. Se si aggiunge l'ordinamento e il filtro del codice nella classe repository e si esegue questa operazione prima della conversione di un'espressione LINQ o di una query dell'oggetto in un IEnumerable oggetto, i comandi verranno passati al database per l'elaborazione, che in genere è più efficiente. In questa esercitazione si implementerà l'ordinamento e il filtro in modo da causare l'esecuzione dell'elaborazione dal database, ovvero nel repository.

Per aggiungere funzionalità di ordinamento, è necessario aggiungere un nuovo metodo all'interfaccia del repository e alle classi di repository, nonché alla classe della logica di business. Nel file ISchoolRepository.cs aggiungere un nuovo metodo che accetta sortExpression un parametro GetDepartments che verrà usato per ordinare l'elenco dei reparti restituiti:

IEnumerable<Department> GetDepartments(string sortExpression);

Il sortExpression parametro specifica la colonna su cui ordinare e la direzione di ordinamento.

Aggiungere codice per il nuovo metodo al file SchoolRepository.cs :

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

Modificare il metodo senza GetDepartments parametri esistente per chiamare il nuovo metodo:

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

Nel progetto di test aggiungere il nuovo metodo seguente a MockSchoolRepository.cs:

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

Se si intende creare eventuali unit test che dipendono da questo metodo che restituisce un elenco ordinato, è necessario ordinare l'elenco prima di restituirlo. Non si creerà test come questo in questa esercitazione, quindi il metodo può solo restituire l'elenco non ordinato dei reparti.

Nel file SchoolBL.cs aggiungere il nuovo metodo seguente alla classe di logica di business:

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

Questo codice passa il parametro di ordinamento al metodo repository.

Eseguire la pagina Departments.aspx .

Immagine02

È ora possibile fare clic su qualsiasi intestazione di colonna per ordinare in base a tale colonna. Se la colonna è già ordinata, fare clic sull'intestazione inverte la direzione di ordinamento.

In questa sezione si aggiungerà una casella di testo di ricerca, collegarla al controllo usando un parametro di controllo e aggiungere un metodo alla classe logica di business per supportare il ObjectDataSource filtro.

Aprire la pagina Departments.aspx e aggiungere il markup seguente tra l'intestazione e il primo ObjectDataSource controllo:

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

ObjectDataSource Nel controllo denominato DepartmentsObjectDataSource, eseguire le operazioni seguenti:

  • Aggiungere un elemento per un SelectParameters parametro denominato nameSearchString che ottiene il valore immesso nel SearchTextBox controllo.
  • Modificare il valore dell'attributo SelectMethod in GetDepartmentsByName. Si creerà questo metodo in un secondo momento.

Il markup per il controllo ora è simile all'esempio ObjectDataSource seguente:

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

In ISchoolRepository.cs aggiungere un GetDepartmentsByName metodo che accetta entrambi sortExpression i parametri:nameSearchString

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

In SchoolRepository.cs aggiungere il nuovo metodo seguente:

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

Questo codice usa un Where metodo per selezionare gli elementi che contengono la stringa di ricerca. Se la stringa di ricerca è vuota, verranno selezionati tutti i record. Si noti che quando si specificano chiamate al metodo in un'istruzione come questa (Include, quindi OrderBy, Where), il Where metodo deve sempre essere ultimo.

Modificare il metodo esistente GetDepartments che accetta un sortExpression parametro per chiamare il nuovo metodo:

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

In MockSchoolRepository.cs nel progetto di test aggiungere il nuovo metodo seguente:

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

In SchoolBL.cs aggiungere il nuovo metodo seguente:

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

Eseguire la pagina Departments.aspx e immettere una stringa di ricerca per assicurarsi che la logica di selezione funzioni. Lasciare vuota la casella di testo e provare una ricerca per assicurarsi che tutti i record vengano restituiti.

Immagine03

Aggiunta di una colonna dettagli per ogni riga di griglia

Successivamente, si desidera visualizzare tutti i corsi per ogni reparto visualizzato nella cella destra della griglia. A tale scopo, si userà un controllo annidato GridView e lo si assegnare ai dati dalla Courses proprietà di spostamento dell'entità Department .

Aprire Departments.aspx e nel markup per il GridView controllo specificare un gestore per l'evento RowDataBound . Il markup per il tag di apertura del controllo ora è simile all'esempio seguente.

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

Aggiungere un nuovo TemplateField elemento dopo il campo modello 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>

Questo markup crea un controllo annidato GridView che mostra il numero di corso e il titolo di un elenco di corsi. Non specifica un'origine dati perché verrà inserita nel codice nel RowDataBound gestore.

Aprire Departments.aspx.cs e aggiungere il gestore seguente per l'evento 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();
    }
}

Questo codice ottiene l'entità dagli argomenti dell'evento, converte la DepartmentCourses proprietà di spostamento in una List raccolta e databinds l'oggetto annidato GridView nella raccolta.

Aprire il file SchoolRepository.cs e specificare il caricamento ansioso per la Courses proprietà di spostamento chiamando il Include metodo nella query dell'oggetto creato nel GetDepartmentsByName metodo . L'istruzione return nel metodo ora è simile all'esempio GetDepartmentsByName seguente.

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

Eseguire la pagina. Oltre alla funzionalità di ordinamento e filtro aggiunta in precedenza, il controllo GridView ora mostra i dettagli del corso annidati per ogni reparto.

Screenshot che mostra il controllo Visualizzazione griglia che visualizza i dettagli del corso annidati.

Questa operazione completa l'introduzione agli scenari di ordinamento, filtro e dettagli master. Nell'esercitazione successiva verrà illustrato come gestire la concorrenza.