Imaginemos, por ejemplo, la siguiente estructura de datos, que podríamos describir diciendo que un usuario puede tener un número indeterminado de blogs, y en cada uno de ellos existirán un número indeterminado de posts:
E imaginemos ahora el siguiente código, que realiza un recorrido en profundidad de estos datos para mostrar los posts de cada blog de cada uno de los usuarios, generando la salida mostrada justo después:
using (var ctx = new MyDataContext())
{
var query = ctx.Users;
foreach (var person in query)
{
Console.WriteLine("User " + person.Name + ":");
foreach (var blog in person.Blogs)
{
Console.WriteLine(" Blog " + blog.Name + ":");
foreach (var post in blog.Posts)
{
Console.WriteLine(" Post: " + post.Title);
}
}
}
}
Por defecto, con lazy loading activado, la ejecución de esta pequeña porción de código habría generado seis consultas a la base de datos:
- Obtener todos los usuarios. Se obtienen dos instancias de
User
. - Obtener todos los blogs del primer usuario (jmaguilar). Se obtienen dos instancias de
Blog
. - Obtener todos los posts del primer blog de jmaguilar. Se obtienen dos instancias de
Post
. - Obtener todos los posts del segundo blog de jmaguilar. Se obtienen dos instancias de
Post
. - Obtener todos los blogs del segundo usuario (johnresig). Se obtiene una instancia de
Blog
. - Obtener todos los posts del único blog del usuario. Se obtiene una instancia de
Post
.
La solución más frecuente es adelantar la carga de las entidades relacionadas, es decir, utilizar eager loading para traerse la estructura completa en una única consulta.
En una estructura como la que hemos visto pero con dos únicos niveles, sería algo así:
using (var ctx = new MyDataContext())La cláusula
{
var query = ctx.Users.Include(u => u.Blogs);
foreach (var person in query)
{
// Code omitted
}
}
Include()
indicará a Entity Framework que cuando realice la consulta a la colección de usuarios debe traerse también la colección de blogs relacionados con cada uno de ellos. Si ejecutamos el ejemplo anterior, podremos comprobar que el número de consultas se ha reducido a cuatro:- Obtener todos los usuarios junto con sus blogs.
- Obtener todos los posts del primer blog del usuario.
- Obtener todos los posts del segundo blog del usuario jmaguilar.
- Obtener todos los posts del blog del usuario johnresig.
Post
asociados con los blogs. Sin embargo, la forma de hacerlo no es tan obvia ni intuitiva como la anterior. No podemos especificarlo en el Include()
, puesto que no es posible referenciar la colección como u.Blogs.Posts
, dado que Posts
no es una propiedad de la colección Blogs
del usuario y fallaría en compilación.La fórmula a emplear en este caso es la siguiente:
using (var ctx = new MyDataContext())Y de esta forma tan simple estaremos obteniendo la estructura de datos completa realizando una única consulta a la base de datos, con el beneficio de rendimiento que esto conlleva.
{
var query = ctx.Users.Include(u => u.Blogs.Select(b => b.Posts));
foreach (var person in query)
{
// Code omitted
}
}
Publicado en: Variable not found.