Entity Framework Core 2.1: Modelos de Query (Trabajando con Vistas)

Hasta ahora, cada uno de los modelos que utilizamos representa una tabla en nuestra base de datos, y, utilizamos dicho modelo para poder hacer queries a dicha tabla. Así, tenemos el modelo Student y la tabla Students, utilizamos entonces algo como context.Students.ToList() para poder traer un listado de estudiantes de la base de datos. Sin embargo, habrá ocasiones en las que queremos utilizar un modelo como resultado de nuestros queries el cual no necesariamente representa una tabla en nuestra base de datos. EF Core 2.1 nos permite resolver este problema utilizando un Modelo de Query.

Un Modelo de Query, o Query Type, es un modelo el cual se asocia con un query o vista, y no con una tabla de nuestra base de datos. A continuación, algunas de las ventajas de utilizar modelos de query:

– Nos da la comodidad de poder expresar el resultado de queries arbitrarios en términos de una clase, así, podemos disfrutar de las ventajas de un lenguaje fuertemente tipado a la hora de consumir queries arbitrarios.
– Nos permite centralizar los queries que hacemos.
– No tenemos que preocuparnos por temas de eficiencia del seguidor de cambios (change tracker), pues por definición, los modelos de query no representan tablas de nuestra base de datos, y por tanto, el seguidor de cambio no les da seguimiento.

Supongamos que tenemos una clase Estudiante, Curso y EstudianteCurso, y que existe una relación muchos a muchos de Estudiante y Curso, representada por EstudianteCurso.

Veamos un primer ejemplo. Queremos centralizar un query de los estudiantes, que traiga su Id, nombre, y fecha de nacimiento. Lo primero que necesitamos es una clase que guarde estos resultados:

public class StudentData
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Birthdate { get; set; }
}

Ahora, con el Api Fluente, podemos realizar la siguiente configuración en el método OnModelCreating:

modelBuilder.Query<StudentData>()
.ToQuery(() => Students.Select(x =>
 new StudentData { Id = x.Id, Name = x.Name, Birthdate = x.Birthdate }));

Fíjate que con el método ToQuery estamos especificando un query. Por tanto, estamos diciendo que cada vez que hablemos con la entidad StudentData, entonces el query que estamos colocando aquí es el que se va a ejecutar. Así tenemos el query el centralizado.

Luego, para poder utilizar este modelo de query:

var students = context.Query<StudentData>().ToList();

Ahora vamos a ver un ejemplo con una vista. Supongamos que tenemos la siguiente vista de nombre StudentsWithActiveCourses:

SELECT        stu.Id, stu.Name, COUNT(*) AS CoursesQuantity
FROM            dbo.Students AS stu 
INNER JOIN
        dbo.StudentsCourses AS sco ON stu.Id = sco.StudentId
WHERE        (sco.IsActive = 'true')
GROUP BY stu.Id, stu.Name

Esta vista nos da el Id de un estudiante, su nombre, y la cantidad de cursos que lleva activos. Podemos correr dicha de vista desde EF Core utilizando un modelo de query. Primero definimos la clase que sostendrá los resultados de la vista:

public class StudentWithCourses
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ActiveCourses { get; set; }
}

Vamos entonces a definir el modelo de query en el OnModelCreating de la siguiente manera:

modelBuilder.Query<StudentWithCourses>().ToView("StudentsWithActiveCourses");

Luego, para utilizar la vista:

var studentWithCourses = context.Query<StudentWithCourses>().ToList();

Hasta ahora hemos utilizado la sintaxis context.Query<Class>() para poder traer los resultados del query correspondiente. Podemos ahorrarnos esto si declaramos el modelo de query utilizando el tipo DbQuery a nivel del Data Context. Esto es bastante similar al uso que le damos a DbSet. En el Data Context, podemos colocar lo siguiente:

public DbQuery<StudentWithCourses> StudentWithCourses { get; set; }

Entonces, para ejecutar la vista, podemos hacer lo siguiente:

var studentWithCourses = context.StudentWithCourses.ToList();

La cual es una sintaxis un poco más legible.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s