entity-framework-4.1 - tools - instalar entity
Entity Framework 4.1 Propiedades virtuales (1)
Si he declarado relación de entidad en mi modelo como virtual, entonces no hay necesidad de usar la instrucción Include
en mi consulta LINQ, ¿verdad? -
Por ejemplo: esta es mi clase de modelo:
public class Brand
{
public int BrandID { get; set; }
public string BrandName { get; set; }
public string BrandDesc { get; set; }
public string BrandUrl { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Ahora, para la clase de modelo anterior, no necesito usar las var brandsAndProduct = pe.Brands.Include("Products").Single(brand => brand.BrandID == 22);
.
En cambio, puedo usar las simples var brandsAndProduct = pe.Brands.Where(brand => brand.BrandID == 22);
y automáticamente tendré la entidad relacionada disponible cuando sea accedida.
¿Estoy en lo correcto en mi comprensión?
Además, ¿por favor dígame en qué situaciones preferiría una sobre la otra?
Tiene razón, pero la regla es más compleja para que funcione realmente como se esperaba. Si define su propiedad de navegación, EF virtual
creará en tiempo de ejecución una nueva clase (proxy dinámico) derivada de su clase de Brand
y la usará en su lugar. Esta nueva clase creada dinámicamente contiene lógica para cargar la propiedad de navegación cuando se accede por primera vez. Esta función se denomina carga diferida (o mejor carga lenta transparente).
Qué reglas deben cumplir para que esto funcione:
- Todas las propiedades de navegación en clase deben ser
virtual
- La creación de proxy dinámico no debe estar deshabilitada (
context.Configuration.ProxyCreationEnabled
). Está habilitado por defecto. - La carga diferida no debe estar deshabilitada (
context.Configuration.LazyLoadingEnabled
). Está habilitado por defecto. - La entidad debe estar adjunta (por defecto si carga la entidad desde la base de datos) al contexto y el contexto no debe eliminarse = la carga diferida funciona solo dentro del contexto del alcance de la vida utilizado para cargarla desde la base de datos (o donde se adjuntó la entidad proxy)
Lo opuesto a la carga diferida se llama carga ansiosa y eso es lo que hace Include
. Si usa Include
su propiedad de navegación se carga junto con la entidad principal.
El uso de carga diferida y carga ansiosa depende de sus necesidades y también del rendimiento. Include
cargas de todos los datos en una consulta de base de datos única, pero puede dar lugar a un gran conjunto de datos cuando se utiliza una gran cantidad de incluye o la carga de muchas entidades. Si está seguro de que necesitará Brand
y todos los Products
para procesar, debe usar la carga ansiosa.
La carga diferida se utiliza a su vez si no está seguro de qué propiedad de navegación necesitará. Por ejemplo, si carga 100 marcas, solo deberá acceder a productos de una marca, no es necesario cargar productos para todas las marcas en la consulta inicial. La desventaja de la carga diferida es la consulta separada (ida y vuelta de la base de datos) para cada propiedad de navegación => si carga 100 marcas sin incluir y accederá a la propiedad de Products
en cada instancia de Brand
su código generará otras 100 consultas para rellenar estas propiedades de navegación = ansioso la carga usaría solo la consulta singe pero la carga diferida usó 101 consultas (se llama problema N + 1).
En escenarios más complejos, puede encontrar que ninguna de estas estrategias funciona como necesita y puede utilizar una tercera estrategia llamada carga explícita o consultas separadas para cargar marcas y productos para todas las marcas que necesita.
La carga explícita tiene desventajas similares a la carga diferida, pero debes activarla manualmente:
context.Entry(brand).Collection(b => b.Products).Load();
Las principales ventajas de la carga explícita es la capacidad de filtrar la relación. Puede usar Query()
antes de Load()
y usar cualquier filtrado o incluso carga ansiosa de relaciones anidadas.