Tutorial: más información sobre escenarios avanzados de EF para una aplicación web de MVC 5

En el tutorial anterior, se implementó la herencia de tabla por jerarquía. En este tutorial se incluyen varios temas que es importante tener en cuenta cuando va más allá de los conceptos básicos del desarrollo de aplicaciones web ASP.NET que usan Entity Framework Core. Las primeras secciones tienen instrucciones paso a paso que le guiarán por el código y el uso de Visual Studio para completar tareas Las siguientes secciones presentan varios temas con breves instrucciones seguidas de vínculos a recursos para obtener más información.

Para la mayoría de estos temas, trabajará con páginas que ya ha creado. Para usar SQL sin procesar para realizar actualizaciones masivas, creará una nueva página que actualiza el número de créditos de todos los cursos de la base de datos:

Update_Course_Credits_initial_page

En este tutorial ha:

  • Realiza consultas SQL sin formato
  • Realización de consultas sin seguimiento
  • Examen de consultas SQL enviadas a la base de datos

También obtendrá información sobre:

  • Creación de una capa de abstracción
  • Clases de proxy
  • Detección de cambios automática
  • Validación automática
  • Entity Framework Power Tools
  • Código fuente de Entity Framework

Requisito previo

Realiza consultas SQL sin formato

La API de Entity Framework Code First incluye métodos que le permiten pasar comandos SQL directamente a la base de datos. Tiene las siguientes opciones:

  • Use el método DbSet.SqlQuery para las consultas que devuelven tipos de entidad. Los objetos devueltos deben ser del tipo esperado por el objeto DbSet y se les realiza automáticamente un seguimiento mediante el contexto de base de datos a menos que se desactive el seguimiento. (Consulte la siguiente sección sobre el método AsNoTracking).
  • Use el método Database.SqlQuery para las consultas que devuelven tipos que no son entidades. No se realiza un seguimiento de los datos devueltos por el contexto de la base de datos, incluso si usa este método para recuperar tipos de entidad.
  • Use el Database.ExecuteSqlCommand para comandos que no son de consulta.

Una de las ventajas del uso de Entity Framework es que evita enlazar el código demasiado estrechamente a un método concreto de almacenamiento de datos. Lo consigue mediante la generación de consultas SQL y comandos, lo que también le evita tener que escribirlos usted mismo. Pero hay situaciones excepcionales en las que necesita ejecutar consultas específicas de SQL que ha creado manualmente y estos métodos permiten controlar estas excepciones.

Como siempre es true cuando ejecuta comandos SQL en una aplicación web, debe tomar precauciones para proteger su sitio contra los ataques por inyección de código SQL. Una manera de hacerlo es mediante consultas parametrizadas para asegurarse de que las cadenas enviadas por una página web no se pueden interpretar como comandos SQL. En este tutorial usará las consultas con parámetros al integrar la entrada de usuario en una consulta.

Llamada a una consulta que devuelve entidades

La clase DbSet<TEntity> proporciona un método que puede usar para ejecutar una consulta que devuelve una entidad de tipo TEntity. Para ver cómo funciona, cambiará el código en el método Details del controlador de Department.

En DepartmentController.cs, en el método Details, reemplace la llamada al método db.Departments.FindAsync por una llamada al método db.Departments.SqlQuery, como se muestra en el código resaltado siguiente:

public async Task<ActionResult> Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    // Commenting out original code to show how to use a raw SQL query.
    //Department department = await db.Departments.FindAsync(id);

    // Create and execute raw SQL query.
    string query = "SELECT * FROM Department WHERE DepartmentID = @p0";
    Department department = await db.Departments.SqlQuery(query, id).SingleOrDefaultAsync();
    
    if (department == null)
    {
        return HttpNotFound();
    }
    return View(department);
}

Para comprobar que el nuevo código funciona correctamente, seleccione la pestaña Departments y, después, Details para uno de los departamentos. Asegúrese de que todos los datos se muestran según lo previsto.

Llamada a una consulta que devuelve otros tipos de objetos

Anteriormente creó una cuadrícula de estadísticas de alumno de la página About que mostraba el número de alumnos para cada fecha de inscripción. El código que lo hace en HomeController.cs usa LINQ:

var data = from student in db.Students
           group student by student.EnrollmentDate into dateGroup
           select new EnrollmentDateGroup()
           {
               EnrollmentDate = dateGroup.Key,
               StudentCount = dateGroup.Count()
           };

Supongamos que desea escribir el código que recupera estos datos directamente en SQL en lugar de usar LINQ. Para ello, debe ejecutar una consulta que devuelva algo distinto de los objetos de entidad, lo que significa que debe usar el método Database.SqlQuery.

En HomeController.cs, reemplace la instrucción LINQ en el método About por una instrucción SQL, como se muestra en el código resaltado siguiente:

public ActionResult About()
{
    // Commenting out LINQ to show how to do the same thing in SQL.
    //IQueryable<EnrollmentDateGroup> = from student in db.Students
    //           group student by student.EnrollmentDate into dateGroup
    //           select new EnrollmentDateGroup()
    //           {
    //               EnrollmentDate = dateGroup.Key,
    //               StudentCount = dateGroup.Count()
    //           };

    // SQL version of the above LINQ code.
    string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
        + "FROM Person "
        + "WHERE Discriminator = 'Student' "
        + "GROUP BY EnrollmentDate";
    IEnumerable<EnrollmentDateGroup> data = db.Database.SqlQuery<EnrollmentDateGroup>(query);

    return View(data.ToList());
}

Ejecute la página Acerca de. Compruebe que muestra los mismos datos que hizo antes.

Llamada a una consulta de actualización

Supongamos que los administradores de Contoso University quieren realizar cambios masivos en la base de datos, como cambiar el número de créditos de cada curso. Si la universidad tiene un gran número de cursos, sería poco eficaz recuperarlos todos como entidades y cambiarlos de forma individual. En esta sección implementará una página web que permite al usuario especificar un factor por el cual se va a cambiar el número de créditos para todos los cursos y podrá realizar el cambio mediante la ejecución de una instrucción UPDATE de SQL.

En CourseController.cs, agregue métodos de UpdateCourseCredits para HttpGet y HttpPost:

public ActionResult UpdateCourseCredits()
{
    return View();
}

[HttpPost]
public ActionResult UpdateCourseCredits(int? multiplier)
{
    if (multiplier != null)
    {
        ViewBag.RowsAffected = db.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);
    }
    return View();
}

Cuando el controlador procesa una solicitud HttpGet, no se devuelve nada en la variable ViewBag.RowsAffected, y la vista muestra un cuadro de texto vacío y un botón enviar.

Cuando se hace clic en el botón Actualizar, se llama al método HttpPost y el multiplier tiene el valor especificado en el cuadro de texto. A continuación, el código ejecuta la instrucción SQL que actualiza los cursos y devuelve el número de filas afectadas a la vista en la variable ViewBag.RowsAffected. Cuando la vista obtiene un valor en esa variable, muestra el número de filas actualizadas en lugar del cuadro de texto y el botón enviar.

En CourseController.cs, haga clic con el botón derecho en uno de los métodos UpdateCourseCredits y, a continuación, haga clic en Agregar vista. Aparece el cuadro de diálogo Agregar vista. Deje los valores predeterminados y seleccione Agregar.

En Views\Course\UpdateCourseCredits.cshtml, reemplace el código de plantilla con el código siguiente:

@model ContosoUniversity.Models.Course

@{
    ViewBag.Title = "UpdateCourseCredits";
}

<h2>Update Course Credits</h2>

@if (ViewBag.RowsAffected == null)
{
    using (Html.BeginForm())
    {
        <p>
            Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
        </p>
        <p>
            <input type="submit" value="Update" />
        </p>
    }
}
@if (ViewBag.RowsAffected != null)
{
    <p>
        Number of rows updated: @ViewBag.RowsAffected
    </p>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Ejecute el método UpdateCourseCredits seleccionando la pestaña Courses, después, agregue "/UpdateCourseCredits" al final de la dirección URL en la barra de direcciones del explorador (por ejemplo: http://localhost:50205/Course/UpdateCourseCredits). Escriba un número en el cuadro de texto:

Update_Course_Credits_initial_page_with_2_entered

Haga clic en Actualizar. Verá el número de filas afectadas.

Haga clic en Volver a la lista para ver la lista de cursos con el número de créditos revisado.

Para obtener más información sobre las consultas SQL básicas, vea Consultas SQL básicas en MSDN.

Consultas de no seguimiento

Cuando un contexto de base de datos recupera las filas de tabla y crea objetos de entidad que las representa, de forma predeterminada realiza el seguimiento de si las entidades en memoria están sincronizadas con el contenido de la base de datos. Los datos en memoria actúan como una caché y se usan cuando se actualiza una entidad. Este almacenamiento en caché suele ser necesario en una aplicación web porque las instancias de contexto normalmente son de corta duración (para cada solicitud se crea una y se elimina) y el contexto que lee una entidad normalmente se elimina antes de volver a usar esa entidad.

Puede deshabilitar el seguimiento de objetos de entidad en memoria mediante el método AsNoTracking. Los siguientes son escenarios típicos en los que es posible que quiera hacer esto:

  • Una consulta recupera un volumen de datos tan grande que desactivar el seguimiento podría mejorar notablemente el rendimiento.
  • Quiere adjuntar una entidad para actualizarla, pero anteriormente recuperó la misma entidad para un propósito diferente. Como el contexto de base de datos ya está realizando el seguimiento de la entidad, no se puede adjuntar la entidad que se quiere cambiar. Una manera de controlar esta situación es usar la opción AsNoTracking con la consulta anterior.

Para obtener un ejemplo que muestra cómo usar el método AsNoTracking, consulte la versión anterior de este tutorial. Esta versión del tutorial no establece la marca Modified en una entidad creada por el enlazador de modelos en el método Edit, por lo que no necesita AsNoTracking.

Examen de SQL enviado a la base de datos

A veces resulta útil poder ver las consultas SQL reales que se envían a la base de datos. En un tutorial anterior, ha visto cómo hacerlo en el código del interceptor; ahora verá algunas maneras de hacerlo sin escribir código interceptor. Para probar esto, verá una consulta sencilla y, a continuación, verá lo que le sucede a medida que agrega opciones como carga diligente, filtrado y ordenación.

En Controllers/CourseController, reemplace el método Index por el siguiente código para detener temporalmente la carga diligente:

public ActionResult Index()
{
    var courses = db.Courses;
    var sql = courses.ToString();
    return View(courses.ToList());
}

Ahora, establezca un punto de interrupción en la instrucción return (F9 con el cursor en esa línea). Presione F5 para ejecutar el proyecto en modo de depuración y seleccione la página Índice del curso. Cuando el código alcance el punto de interrupción, examine la variable sql. Verá la consulta que se envía a SQL Server. Es una instrucción Select simple.

{SELECT 
[Extent1].[CourseID] AS [CourseID], 
[Extent1].[Title] AS [Title], 
[Extent1].[Credits] AS [Credits], 
[Extent1].[DepartmentID] AS [DepartmentID]
FROM [Course] AS [Extent1]}

Haga clic en la lupa para ver la consulta en el visualizador de texto.

One screenshot that shows the Course Controller with a line of code highlighted. Another screenshot that shows the Text Visualizer open and a magnifying glass is circled in red in the Value field.

Ahora agregará una lista desplegable a la página Índice de cursos para que los usuarios puedan filtrar por un departamento determinado. Ordenará los cursos por título y especificará la carga diligente de la propiedad de navegación Department.

En CourseController.cs, reemplace el método Index por el siguiente código:

public ActionResult Index(int? SelectedDepartment)
{
    var departments = db.Departments.OrderBy(q => q.Name).ToList();
    ViewBag.SelectedDepartment = new SelectList(departments, "DepartmentID", "Name", SelectedDepartment);
    int departmentID = SelectedDepartment.GetValueOrDefault();

    IQueryable<Course> courses = db.Courses
        .Where(c => !SelectedDepartment.HasValue || c.DepartmentID == departmentID)
        .OrderBy(d => d.CourseID)
        .Include(d => d.Department);
    var sql = courses.ToString();
    return View(courses.ToList());
}

Restaure el punto de interrupción en la instrucción return.

El método recibe el valor seleccionado de la lista desplegable en el parámetro SelectedDepartment. Si no se selecciona nada, este parámetro será null.

Se pasa una colección SelectList que contiene todos los departamentos a la vista de la lista desplegable. Los parámetros pasados al constructor SelectList especifican el nombre del campo de valor, el nombre del campo de texto y el elemento seleccionado.

Para el método Get del repositorio Course, el código especifica una expresión de filtro, un criterio de ordenación y una carga diligente para la propiedad de navegación Department. La expresión de filtro siempre devuelve true si no se selecciona nada en la lista desplegable (es decir, SelectedDepartment es null).

En Views\Course\Index.cshtml, inmediatamente antes de la etiqueta de apertura table, agregue el siguiente código para crear la lista desplegable y un botón enviar:

@using (Html.BeginForm())
{
    <p>Select Department: @Html.DropDownList("SelectedDepartment","All")   
    <input type="submit" value="Filter" /></p>
}

Con el punto de interrupción aún establecido, ejecute la página Índice del curso. Continúe por las primeras veces que el código alcanza un punto de interrupción, de modo que la página se muestre en el explorador. Seleccione un departamento en la lista desplegable y haga clic en Filtrar.

Esta vez el primer punto de interrupción será para la consulta de departamentos para la lista desplegable. Omita eso y vea la variable query la próxima vez que el código alcance el punto de interrupción para ver el aspecto de la consulta Course. Verá algo parecido a lo siguiente:

SELECT 
    [Project1].[CourseID] AS [CourseID], 
    [Project1].[Title] AS [Title], 
    [Project1].[Credits] AS [Credits], 
    [Project1].[DepartmentID] AS [DepartmentID], 
    [Project1].[DepartmentID1] AS [DepartmentID1], 
    [Project1].[Name] AS [Name], 
    [Project1].[Budget] AS [Budget], 
    [Project1].[StartDate] AS [StartDate], 
    [Project1].[InstructorID] AS [InstructorID], 
    [Project1].[RowVersion] AS [RowVersion]
    FROM ( SELECT 
        [Extent1].[CourseID] AS [CourseID], 
        [Extent1].[Title] AS [Title], 
        [Extent1].[Credits] AS [Credits], 
        [Extent1].[DepartmentID] AS [DepartmentID], 
        [Extent2].[DepartmentID] AS [DepartmentID1], 
        [Extent2].[Name] AS [Name], 
        [Extent2].[Budget] AS [Budget], 
        [Extent2].[StartDate] AS [StartDate], 
        [Extent2].[InstructorID] AS [InstructorID], 
        [Extent2].[RowVersion] AS [RowVersion]
        FROM  [dbo].[Course] AS [Extent1]
        INNER JOIN [dbo].[Department] AS [Extent2] ON [Extent1].[DepartmentID] = [Extent2].[DepartmentID]
        WHERE @p__linq__0 IS NULL OR [Extent1].[DepartmentID] = @p__linq__1
    )  AS [Project1]
    ORDER BY [Project1].[CourseID] ASC

Puede ver que la consulta es ahora una consulta JOIN que carga datos Department junto con los datos Course y que incluye una cláusula WHERE.

Quite la línea var sql = courses.ToString().

Crea una capa de abstracción

Muchos desarrolladores escriben código para implementar el repositorio y una unidad de patrones de trabajo como un contenedor en torno al código que funciona con Entity Framework. Estos patrones están previstos para crear una capa de abstracción entre la capa de acceso de datos y la capa de lógica de negocios de una aplicación. Implementar estos patrones puede ayudar a aislar la aplicación de cambios en el almacén de datos y puede facilitar la realización de pruebas unitarias automatizadas o el desarrollo controlado por pruebas (TDD). Pero escribir código adicional para implementar estos patrones no siempre es la mejor opción para las aplicaciones que usan EF, por varias razones:

  • La propia clase de contexto de EF aísla el código del código específico del almacén de datos.
  • La clase de contexto de EF puede actuar como una clase de unidad de trabajo para las actualizaciones de base de datos que hace con EF.
  • Las características introducidas en Entity Framework 6 facilitan la implementación de TDD sin escribir código de repositorio.

Para obtener más información sobre cómo implementar los patrones de repositorio y de unidad de trabajo, consulte la versión de Entity Framework 5 de esta serie de tutoriales. Para obtener información sobre las formas de implementar TDD en Entity Framework 6, consulte los siguientes recursos:

Clases de proxy

Cuando Entity Framework crea instancias de entidad (por ejemplo, al ejecutar una consulta), a menudo las crea como instancias de un tipo derivado generado dinámicamente que actúa como proxy para la entidad. Por ejemplo, consulte las siguientes dos imágenes del depurador. En la primera imagen, verá que la variable student es el tipo de Student esperado inmediatamente después de crear una instancia de la entidad. En la segunda imagen, después de que EF se haya usado para leer una entidad de estudiante de la base de datos, verá la clase proxy.

Before proxy class

After proxy class

Esta clase proxy invalida algunas propiedades virtuales de la entidad para insertar enlaces para realizar acciones automáticamente cuando se accede a la propiedad. Una función para la que se usa este mecanismo es la carga diferida.

La mayoría de las veces no es necesario tener en cuenta este uso de servidores proxy, pero hay excepciones:

  • En algunos escenarios, es posible que quiera impedir que Entity Framework cree instancias de proxy. Por ejemplo, al serializar entidades, normalmente quiere las clases POCO, no las clases de proxy. Una manera de evitar problemas de serialización es serializar objetos de transferencia de datos (DTO) en lugar de objetos de entidad, como se muestra en el tutorial Uso de API web con Entity Framework. Otra manera es deshabilitar la creación de proxy.
  • Al crear una instancia de una clase de entidad mediante el operador new, no se obtiene una instancia de proxy. Esto significa que no obtiene funcionalidad como la carga diferida y el seguimiento automático de cambios. Esto suele estar bien; por lo general, no necesita carga diferida, ya que va a crear una nueva entidad que no está en la base de datos y, por lo general, no necesita seguimiento de cambios si está marcando explícitamente la entidad como Added. Sin embargo, si necesita carga diferida y seguimiento de cambios, puede crear nuevas instancias de entidad con servidores proxy mediante el método Create de la clase DbSet.
  • Es posible que quiera obtener un tipo de entidad real de un tipo de proxy. Puede usar el método GetObjectType de la clase ObjectContext para obtener el tipo de entidad real de una instancia de tipo proxy.

Para obtener más información, consulte Trabajar con servidores proxy en MSDN.

Detección de cambios automática

Entity Framework determina cómo ha cambiado una entidad (y, por tanto, las actualizaciones que hay que enviar a la base de datos) comparando los valores actuales de una entidad con los valores originales. Cuando se consulta o se adjunta la entidad, se almacenan los valores originales. Algunos de los métodos que provocan la detección de cambios automática son los siguientes:

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

Si está realizando el seguimiento de un gran número de entidades y llama a uno de estos métodos muchas veces en un bucle, podría obtener mejoras de rendimiento significativas si desactiva temporalmente la detección de cambios automática mediante la propiedad AutoDetectChangesEnabled. Para obtener más información, consulte Detección automática de cambios en MSDN.

Validación automática

Cuando se llama al método SaveChanges, de forma predeterminada, Entity Framework valida los datos en todas las propiedades de todas las entidades modificadas antes de actualizar la base de datos. Si ha actualizado un gran número de entidades y ya ha validado los datos, este trabajo no es necesario y podría hacer que el proceso de guardar los cambios tarde menos tiempo al desactivar temporalmente la validación. Puede hacerlo mediante la propiedad ValidateOnSaveEnabled. Para obtener más información, consulte Validación en MSDN.

Entity Framework Power Tools

Entity Framework Power Tools es un complemento de Visual Studio que se usó para crear los diagramas del modelo de datos que se muestran en estos tutoriales. Las herramientas también pueden realizar otras funciones, como generar clases de entidad basadas en las tablas de una base de datos existente para poder usar la base de datos con Code First. Después de instalar las herramientas, aparecen algunas opciones adicionales en los menús contextuales. Por ejemplo, al hacer clic con el botón derecho en la clase de contexto en Explorador de soluciones, verá la opción y Entity Framework. Esto le ofrece la capacidad de generar un diagrama. Cuando usa Code First, no puede cambiar el modelo de datos en el diagrama, pero puede mover las cosas para facilitar su comprensión.

EF diagram

Código fuente de Entity Framework

El código fuente de Entity Framework 6 está disponible en GitHub. Puede archivar errores y puede contribuir a sus propias mejoras en el código fuente de EF.

Aunque el código fuente es abierto, Entity Framework es totalmente compatible como producto de Microsoft. El equipo de Microsoft Entity Framework mantiene el control sobre qué contribuciones se aceptan y comprueba todos los cambios de código para garantizar la calidad de cada versión.

Agradecimientos

  • Tom Dykstra escribió la versión original de este tutorial, coautorizó la actualización de EF 5 y escribió la actualización de EF 6. Tom es un escritor de programación sénior en el equipo de contenido de herramientas y plataforma web de Microsoft.
  • Rick Anderson (twitter @RickAndMSFT) hizo la mayor parte del trabajo actualizando el tutorial para EF 5 y MVC 4 y es coautor de la actualización de EF 6. Rick es un escritor de programación sénior para Microsoft que se centra en Azure y MVC.
  • Rowan Miller y otros miembros del equipo de Entity Framework ayudaron a revisar el código y a depurar muchos problemas con las migraciones que se produjeron mientras actualizamos el tutorial para EF 5 y EF 6.

Solucionar errores habituales

No se puede crear o instantánear

Mensaje de error:

No se puede crear o instantánear "<filename>" cuando ese archivo ya existe.

Solución

Espere unos segundos y actualice la página.

Update-Database no reconocido

Mensaje de error (desde el comando Update-Database en PMC):

El término 'Update-Database' no se reconoce como nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe si escribió correctamente el nombre o, si incluyó una ruta de acceso, compruebe que dicha ruta es correcta e inténtelo de nuevo.

Solución

Salga de Visual Studio. Vuelva a abrir el proyecto e inténtelo de nuevo.

Error de validación

Mensaje de error (desde el comando Update-Database en PMC):

Error de validación para una o varias entidades. Consulte la propiedad "EntityValidationErrors" para obtener más detalles.

Solución

Una causa de este problema es los errores de validación cuando se ejecuta el método Seed. Consulte Bases de datos de inicialización y depuración de Entity Framework (EF) para obtener sugerencias sobre cómo depurar el método Seed.

Error HTTP 500.19

Mensaje de error:

Error HTTP 500.19: error interno del servidor No se puede tener acceso a la página solicitada porque los datos de configuración relacionados de la página no son válidos.

Solución

Una manera de obtener este error es tener varias copias de la solución, cada una de ellas con el mismo número de puerto. Normalmente, puede resolver este problema si sale de todas las instancias de Visual Studio y, a continuación, reinicia el proyecto en el que está trabajando. Si eso no funciona, intente cambiar el número de puerto. Haga clic con el botón derecho en el archivo del proyecto y, a continuación, haga clic en propiedades. Seleccione la pestaña Web y, a continuación, cambie el número de puerto en el cuadro de texto Dirección URL del proyecto.

Error al buscar la instancia de SQL Server

Mensaje de error:

Error relacionado con la red o específico de la instancia mientras se establecía una conexión con el servidor SQL Server. No se encontró el servidor o no era accesible. Compruebe que el nombre de la instancia es correcto y que SQL Server está configurado para admitir conexiones remotas. (proveedor: Interfaces de red SQL, error: 26: error al buscar el servidor o la instancia especificados)

Solución

Compruebe la cadena de conexión. Si ha eliminado manualmente la base de datos, cambie el nombre de la base de datos en la cadena de construcción.

Obtención del código

Descargar el proyecto completado

Recursos adicionales

Para obtener más información sobre cómo trabajar con datos mediante Entity Framework, consulte la página de documentación de EF de en MSDN y Acceso a datos de ASP.NET: recursos recomendados.

Para obtener más información sobre cómo implementar la aplicación web después de compilarla, consulte Implementación web de ASP.NET: recursos recomendados en la biblioteca de MSDN.

Para obtener información sobre otros temas relacionados con MVC, como la autenticación y la autorización, consulte la ASP.NET MVC: recursos recomendados.

Pasos siguientes

En este tutorial ha:

  • Realizado consultas SQL sin formato
  • Consultas sin seguimiento realizadas
  • Consultas SQL examinadas enviadas a la base de datos

Además, ha aprendido lo siguiente:

  • Creación de una capa de abstracción
  • Clases de proxy
  • Detección de cambios automática
  • Validación automática
  • Entity Framework Power Tools
  • Código fuente de Entity Framework

Con esto finaliza esta serie de tutoriales sobre cómo usar Entity Framework en una aplicación ASP.NET MVC. Si desea obtener información sobre EF Database First, consulte la serie de tutoriales de DB First.