¿Qué hace Include () en LINQ?

93

Traté de investigar mucho, pero soy más un tipo de base de datos, por lo que incluso la explicación en MSDN no tiene ningún sentido para mí. ¿Alguien puede explicar y proporcionar algunos ejemplos sobre lo Include()que hace la declaración en el término de SQLconsulta?

CJ
fuente
Muy básico, solo conozco simple Seleccionar, Dónde, Ordenar por, algunos operadores agregados. No he probado JOIN en LINQ, ni Include. Mi objetivo final era poder reescribir estas consultas LINQ en SQL
CJ

Respuestas:

165

Digamos, por ejemplo, que desea obtener una lista de todos sus clientes:

var customers = context.Customers.ToList();

Y supongamos que cada Customerobjeto tiene una referencia a su conjunto de Orders, y que cada uno Ordertiene referencias a las LineItemsque también pueden hacer referencia a Product.

Como puede ver, la selección de un objeto de nivel superior con muchas entidades relacionadas podría resultar en una consulta que necesita obtener datos de muchas fuentes. Como medida de rendimiento, le Include()permite indicar qué entidades relacionadas deben leerse de la base de datos como parte de la misma consulta.

Usando el mismo ejemplo, esto podría traer todos los encabezados de orden relacionados, pero ninguno de los otros registros:

var customersWithOrderDetail = context.Customers.Include("Orders").ToList();

Como punto final, ya que solicitó SQL, la primera declaración sin Include()podría generar una declaración simple:

SELECT * FROM Customers;

La declaración final que llama Include("Orders")puede verse así:

SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;
¡Qué asco!
fuente
1
Gracias. Usando su ejemplo, puedo decir si quiero incluir también LineItemsy Products, la consulta LINQ debería verse así var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();:?
CJ
2
Sí, puede encadenar varias llamadas Include()para capturar objetos a lo largo de diferentes "rutas". Si desea objetos en la misma ruta, solo tiene que realizar una llamada que especifique la ruta completa. Dado LineItemsy Productsno comparten ninguna componentes de la ruta que usted necesita llamadas separadas.
Yuck
¿Es obligatorio utilizar Incluir? Estoy bastante seguro de que trabajé en soluciones en las que podría obtener objetos relacionados sin usarlos.
Jepzen
@Jepzen Depende de si estás usando entidades cargadas de forma diferida o no.
Yuck
@Yuck, creo que esto funciona cuando estás usando la carga diferida, en caso de carga ansiosa, no necesitas usar la declaración "include", pero esto definitivamente resultará en problemas de rendimiento. Por favor corríjame en esto.
sam
27

Solo quería agregar que "Incluir" es parte de una carga ansiosa. Se describe en el tutorial de Entity Framework 6 de Microsoft. Aquí está el enlace: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the -entity-framework-en-una-aplicación-asp-net-mvc


Extracto de la página vinculada:

Aquí hay varias formas en que Entity Framework puede cargar datos relacionados en las propiedades de navegación de una entidad:

Carga lenta.Cuando se lee la entidad por primera vez, no se recuperan los datos relacionados. Sin embargo, la primera vez que intenta acceder a una propiedad de navegación, los datos necesarios para esa propiedad de navegación se recuperan automáticamente. Esto da como resultado varias consultas enviadas a la base de datos, una para la entidad en sí y una cada vez que se deben recuperar los datos relacionados para la entidad. La clase DbContext habilita la carga diferida de forma predeterminada.

Carga ansiosa. Cuando se lee la entidad, los datos relacionados se recuperan junto con ella. Por lo general, esto da como resultado una única consulta de combinación que recupera todos los datos necesarios. Especifica la carga ansiosa utilizando el Includemétodo.

Carga explícita. Esto es similar a la carga diferida, excepto que recupera explícitamente los datos relacionados en el código; no sucede automáticamente cuando accede a una propiedad de navegación. Los datos relacionados se cargan manualmente obteniendo la entrada del administrador de estado del objeto para una entidad y llamando al método Collection.Load para colecciones o al método Reference.Load para propiedades que contienen una sola entidad. (En el siguiente ejemplo, si quisiera cargar la propiedad de navegación del Administrador, la reemplazaría Collection(x => x.Courses)por Reference(x => x.Administrator)). Normalmente, usaría la carga explícita solo cuando haya desactivado la carga diferida.

Debido a que no recuperan inmediatamente los valores de propiedad, la carga diferida y la carga explícita también se conocen como carga diferida.

Minoosha
fuente
3
Bienvenido a SO =) Solo una sugerencia, pero cuando responda algo así, si puede, incluya un fragmento de código. Desafortunadamente, los enlaces pueden fallar.
The_Cthulhu_Kid
2

Piense en ello como imponer la carga ansiosa en un escenario en el que sus subelementos serían de carga diferida.

La consulta EF que se envía a la base de datos producirá un resultado mayor al principio, pero al acceder no se realizarán consultas de seguimiento al acceder a los elementos incluidos.

Por otro lado, sin él, EF ejecutaría consultas separadas más tarde, cuando acceda por primera vez a los subelementos.

robkrueger
fuente