Introducción a Entity Framework 4.0 Database First y ASP.NET 4 Web Forms: parte 3
por Tom Dykstra
La aplicación web de ejemplo de Contoso University muestra cómo crear aplicaciones ASP.NET Web Forms utilizando Entity Framework 4.0 y Visual Studio 2010. Para obtener información sobre la serie de tutoriales, consulte el primer tutorial de la serie
Filtrado, ordenación y agrupación de datos
En el tutorial anterior usó el control EntityDataSource
para mostrar y editar datos. En este tutorial filtrará, ordenará y agrupará los datos. Al hacerlo estableciendo las propiedades del control EntityDataSource
, la sintaxis es diferente de otros controles de origen de datos. Sin embargo, como verá, puede usar el control QueryExtender
para minimizar estas diferencias.
Cambiará la página Students.aspx para filtrar los alumnos, ordenar por nombre y buscar en nombre. También cambiará la página de Courses.aspx para mostrar cursos para el departamento seleccionado y buscar cursos por nombre. Por último, agregará estadísticas de alumnos a la página de About.aspx.
Usar la propiedad "Where" de EntityDataSource para filtrar datos
Abra la página Students.aspx que creó en el tutorial anterior. Como se ha configurado actualmente, el control GridView
de la página muestra todos los nombres del conjunto de entidades People
. Sin embargo, solo quiere mostrar a los alumnos, que puede encontrar seleccionando Person
entidades que tienen fechas de inscripción no nulas.
Cambie a vista Diseño y seleccione el control EntityDataSource
. En la ventana Propiedades , establezca la propiedad Where
en it.EnrollmentDate is not null
.
La sintaxis que se usa en la propiedad Where
del control EntityDataSource
es Entity SQL. Entity SQL es similar a Transact-SQL, pero se personaliza para su uso con entidades en lugar de objetos de base de datos. En la expresión it.EnrollmentDate is not null
, la palabra it
representa una referencia a la entidad devuelta por la consulta. Por lo tanto, it.EnrollmentDate
hace referencia a la propiedad EnrollmentDate
de la entidad Person
que devuelve el control EntityDataSource
.
Ejecute la página. La lista de alumnos ahora solo contiene alumnos. (No se muestran filas donde no hay ninguna fecha de inscripción).
Uso de la propiedad EntityDataSource "OrderBy" para ordenar datos
También desea que esta lista esté en orden de nombres cuando se muestre por primera vez. Con la página Students.aspx todavía abierta en vista Diseño y con el control EntityDataSource
aún seleccionado, en la ventana Propiedades, establezca la propiedad OrderBy en it.LastName
.
Ejecute la página. La lista de alumnos está ahora ordenada por apellidos.
Usar un parámetro de control para establecer la propiedad "Where"
Al igual que con otros controles de origen de datos, puede pasar valores de parámetro a la propiedad Where
. En la página Courses.aspx que creó en la parte 2 del tutorial, puede usar este método para mostrar cursos asociados al departamento que un usuario selecciona en la lista desplegable.
Abra Courses.aspx y cambie a vista Diseño. Agregue un segundo control EntityDataSource
a la página y nómbrelo CoursesEntityDataSource
. Conéctelo al modelo de SchoolEntities
y seleccione Courses
como valor EntitySetName.
En la ventana Propiedades, haga clic en los puntos suspensivos del cuadro de propiedades Where. (Asegúrese de que el control CoursesEntityDataSource
sigue seleccionado antes de utilizar la ventana Propiedades).
Aparecerá el cuadro de diálogo Editor de expresiones. En este cuadro de diálogo, seleccione Generar automáticamente la expresión Where en función de los parámetros proporcionados y luego haga clic en Agregar parámetro. Asigne un nombre al parámetro DepartmentID
, seleccione Control como valor Origen del parámetro y seleccione DepartmentsDropDownList como valor de ControlID.
Haga clic en Mostrar propiedades avanzadas y, en la ventana Propiedades del cuadro de diálogo Editor de expresiones, cambie la propiedad Type
a Int32
.
Cuando haya terminado, haga clic en Aceptar.
Debajo de la lista desplegable, agregue un control GridView
a la página y asígnele el nombre CoursesGridView
. Conéctelo al control de origen de datos CoursesEntityDataSource
, haga clic en Actualizar esquema, haga clic en Editar columnas y quite la columna DepartmentID
. El marcado de control GridView
es similar al siguiente ejemplo.
<asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False"
DataKeyNames="CourseID" DataSourceID="CoursesEntityDataSource">
<Columns>
<asp:BoundField DataField="CourseID" HeaderText="ID" ReadOnly="True"
SortExpression="CourseID" />
<asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
<asp:BoundField DataField="Credits" HeaderText="Credits"
SortExpression="Credits" />
</Columns>
</asp:GridView>
Cuando el usuario cambia el departamento seleccionado en la lista desplegable, quiere que la lista de cursos asociados cambie automáticamente. Para ello, seleccione la lista desplegable y, en la ventana Propiedades, establezca la propiedad AutoPostBack
en True
.
Ahora que ha terminado de utilizar el diseñador, cambie a la vista Origen y sustituya las propiedades ConnectionString
y DefaultContainer
del control CoursesEntityDataSource
por el atributo ContextTypeName="ContosoUniversity.DAL.SchoolEntities"
. Cuando haya terminado, el marcado del control tendrá un aspecto similar al del siguiente ejemplo.
<asp:EntityDataSource ID="CoursesEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false"
EntitySetName="Courses"
AutoGenerateWhereClause="true" Where="">
<WhereParameters>
<asp:ControlParameter ControlID="DepartmentsDropDownList" Type="Int32"
Name="DepartmentID" PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
Ejecute la página y use la lista desplegable para seleccionar diferentes departamentos. Solo se muestran los cursos ofrecidos por el departamento seleccionado en el control GridView
.
Uso de la propiedad "GroupBy" de EntityDataSource para agrupar datos
Supongamos que Contoso University quiere colocar algunas estadísticas de cuerpo de alumnos en su página Acerca de. En concreto, quiere mostrar un desglose de los números de alumnos por la fecha en que se inscribió.
Abra About.aspxy, en vista Origen, reemplace el contenido existente del control BodyContent
por "Estadísticas del cuerpo del alumno" entre etiquetas h2
:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>Student Body Statistics</h2>
</asp:Content>
Después del encabezado, agregue un control EntityDataSource
y asígnele el nombre StudentStatisticsEntityDataSource
. Conéctelo a SchoolEntities
, seleccione el conjunto de entidades People
y no modifique la casilla Seleccionar del asistente. Establezca las siguientes propiedades en la ventana Propiedades:
- Para filtrar solo los alumnos, establezca la propiedad
Where
enit.EnrollmentDate is not null
. - Para agrupar los resultados por la fecha de inscripción, establezca la propiedad
GroupBy
enit.EnrollmentDate
. - Para seleccionar la fecha de inscripción y el número de alumnos, establezca la propiedad
Select
enit.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents
. - Para ordenar los resultados por la fecha de inscripción, establezca la propiedad
OrderBy
enit.EnrollmentDate
.
En la vista Origen, reemplace las propiedades de nombre ConnectionString
y DefaultContainer
por una propiedad ContextTypeName
. El marcado de control EntityDataSource
ahora es similar al siguiente ejemplo.
<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People"
Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents"
OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate"
Where="it.EnrollmentDate is not null" >
</asp:EntityDataSource>
La sintaxis de las propiedades de Select
, GroupBy
y Where
es similar a Transact-SQL, excepto la palabra clave it
que especifica la entidad actual.
Agregue el marcado siguiente para crear un control GridView
para mostrar los datos.
<asp:GridView ID="StudentStatisticsGridView" runat="server" AutoGenerateColumns="False"
DataSourceID="StudentStatisticsEntityDataSource">
<Columns>
<asp:BoundField DataField="EnrollmentDate" DataFormatString="{0:d}"
HeaderText="Date of Enrollment"
ReadOnly="True" SortExpression="EnrollmentDate" />
<asp:BoundField DataField="NumberOfStudents" HeaderText="Students"
ReadOnly="True" SortExpression="NumberOfStudents" />
</Columns>
</asp:GridView>
Ejecute la página para ver una lista que muestra el número de alumnos por fecha de inscripción.
Usar el control QueryExtender para filtrar y ordenar
El control QueryExtender
proporciona una manera de especificar el filtrado y la ordenación en el marcado. La sintaxis es independiente del sistema de administración de bases de datos (DBMS) que está usando. También es generalmente independiente de Entity Framework, con la excepción de que la sintaxis que se usa para las propiedades de navegación es única para Entity Framework.
En esta parte del tutorial, usará un control QueryExtender
para filtrar y ordenar los datos, y uno de los campos order-by será una propiedad de navegación.
(Si prefiere usar código en lugar de marcado para ampliar las consultas generadas automáticamente por el control EntityDataSource
, puede hacerlo controlando el evento QueryCreated
. Así es como el control QueryExtender
extiende también las consultas de control EntityDataSource
).
Abra la página Courses.aspx y, debajo del marcado que agregó anteriormente, inserte el siguiente marcado para crear un encabezado, un cuadro de texto para escribir cadenas de búsqueda, un botón de búsqueda y un control EntityDataSource
enlazado al conjunto de entidades de Courses
.
<h2>Courses by Name</h2>
Enter a course name
<asp:TextBox ID="SearchTextBox" runat="server"></asp:TextBox>
<asp:Button ID="SearchButton" runat="server" Text="Search" />
<br /><br />
<asp:EntityDataSource ID="SearchEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="Courses"
Include="Department" >
</asp:EntityDataSource>
Observe que la propiedad Include
del control EntityDataSource
está establecida en Department
. En la base de datos, la tabla Course
no contiene el nombre del departamento; contiene una columna de clave externa DepartmentID
. Si estaba consultando la base de datos directamente, para obtener el nombre del departamento junto con los datos del curso, tendría que combinar las tablas de Course
y Department
. Al establecer la propiedad Include
en Department
, especifique que Entity Framework debe realizar el trabajo de obtener la entidad Department
relacionada cuando obtiene una entidad Course
. A continuación, la entidad Department
se almacena en la propiedad de navegación Department
de la entidad Course
. (De forma predeterminada, la clase SchoolEntities
generada por el diseñador de modelos de datos recupera los datos relacionados cuando es necesario y ha enlazado el control de origen de datos a esa clase, por lo que no es necesario establecer la propiedad Include
. Sin embargo, la configuración mejora el rendimiento de la página, ya que, de lo contrario, Entity Framework realizaría llamadas independientes a la base de datos para recuperar datos de las entidades de Course
y para las entidades Department
relacionadas).
Después del control EntityDataSource
que acaba de crear, inserte el siguiente marcado para crear un control QueryExtender
enlazado a ese control EntityDataSource
.
<asp:QueryExtender ID="SearchQueryExtender" runat="server"
TargetControlID="SearchEntityDataSource" >
<asp:SearchExpression SearchType="StartsWith" DataFields="Title">
<asp:ControlParameter ControlID="SearchTextBox" />
</asp:SearchExpression>
<asp:OrderByExpression DataField="Department.Name" Direction="Ascending">
<asp:ThenBy DataField="Title" Direction="Ascending" />
</asp:OrderByExpression>
</asp:QueryExtender>
El elemento SearchExpression
especifica que desea seleccionar cursos cuyos títulos coincidan con el valor especificado en el cuadro de texto. Solo se compararán tantos caracteres como se escriban en el cuadro de texto, ya que la propiedad SearchType
especifica StartsWith
.
El elemento OrderByExpression
especifica que el conjunto de resultados se ordenará por título de curso dentro del nombre del departamento. Observe cómo se especifica el nombre del departamento: Department.Name
. Dado que la asociación entre la entidad Course
y la entidad Department
es uno a uno, la propiedad de navegación Department
contiene una entidad Department
. (Si se tratara de una relación uno a muchos, la propiedad contendría una colección). Para obtener el nombre del departamento, debe especificar la propiedad Name
de la entidad Department
.
Por último, agregue un control GridView
para mostrar la lista de cursos:
<asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False"
DataKeyNames="CourseID" DataSourceID="SearchEntityDataSource" AllowPaging="true">
<Columns>
<asp:TemplateField HeaderText="Department">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Eval("Department.Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CourseID" HeaderText="ID"/>
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="Credits" HeaderText="Credits" />
</Columns>
</asp:GridView>
La primera columna es un campo de plantilla que muestra el nombre del departamento. La expresión de enlace de datos especifica Department.Name
, tal como vio en el control QueryExtender
.
Ejecute la página. La presentación inicial muestra una lista de todos los cursos en orden por departamento y, a continuación, por título del curso.
Escriba "m" y haga clic en Buscar para ver todos los cursos cuyos títulos comienzan por "m" (la búsqueda no distingue mayúsculas de minúsculas).
Uso del operador "Me gusta" para filtrar datos
Puede lograr un efecto similar al de QueryExtender
los StartsWith
tipos de búsqueda , Contains
y EndsWith
del control mediante un Like
operador en la EntityDataSource
propiedad del Where
control. En esta parte del tutorial, verá cómo usar el operador Like
para buscar un alumno por nombre.
Abra Students.aspx en la vista de Origen. Después del control GridView
, agregue el siguiente marcado:
<h2>Find Students by Name</h2>
Enter any part of the name
<asp:TextBox ID="SearchTextBox" runat="server" AutoPostBack="true"></asp:TextBox>
<asp:Button ID="SearchButton" runat="server" Text="Search" />
<br />
<br />
<asp:EntityDataSource ID="SearchEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People"
Where="it.EnrollmentDate is not null and (it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%')" >
<WhereParameters>
<asp:ControlParameter ControlID="SearchTextBox" Name="StudentName" PropertyName="Text"
Type="String" DefaultValue="%"/>
</WhereParameters>
</asp:EntityDataSource>
<asp:GridView ID="SearchGridView" runat="server" AutoGenerateColumns="False" DataKeyNames="PersonID"
DataSourceID="SearchEntityDataSource" AllowPaging="true">
<Columns>
<asp:TemplateField HeaderText="Name" SortExpression="LastName, FirstMidName">
<ItemTemplate>
<asp:Label ID="LastNameFoundLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
<asp:Label ID="FirstNameFoundLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
<ItemTemplate>
<asp:Label ID="EnrollmentDateFoundLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Este marcado es similar al que ha visto anteriormente, excepto el valor de la propiedad Where
. La segunda parte de la expresión Where
define una búsqueda de subcadenas (LIKE %FirstMidName% or LIKE %LastName%
) que busca tanto en el nombre como en el apellido lo que se introduzca en el cuadro de texto.
Ejecute la página. Inicialmente verá todos los alumnos porque el valor predeterminado del parámetro StudentName
es "%".
Escriba la letra "g" en el cuadro de texto y haga clic en Buscar. Verá una lista de alumnos que tienen un "g" en el nombre o el apellido.
Ahora ha mostrado, actualizado, filtrado, ordenado y agrupado datos de tablas individuales. En el siguiente tutorial, comenzará a trabajar con datos relacionados (escenarios de maestro y detalle).