framework c# entity-framework virtual entity-framework-core navigation-properties

c# - framework - la propiedad de navegación debe ser virtual, ¿no se requiere en ef core?



entity framework core (5)

Actualización: una implementación inicial de carga diferida, planificada para EF Core 2.1, requerirá que las propiedades de navegación se declaren virtuales. Consulte https://github.com/aspnet/EntityFrameworkCore/issues/10787 , y de manera más general para realizar un seguimiento del progreso en la carga diferida, consulte https://github.com/aspnet/EntityFrameworkCore/issues/10509 .

Como recuerdo en EF , la propiedad de navegación debe ser virtual :

public class Blog { public int BlogId { get; set; } public string Name { get; set; } public string Url { get; set; } public string Tags { get; set; } public virtual ICollection<Post> Posts { get; set; } }

Pero miro a EF Core y no lo veo como virtual:

public class Student { public int ID { get; set; } public string LastName { get; set; } public string FirstMidName { get; set; } public DateTime EnrollmentDate { get; set; } public ICollection<Enrollment> Enrollments { get; set; } }

¿Ya no es necesario?


En EF Core ha elegido el camino de desalentar la carga diferida por defecto. También creo que esta característica todavía no se implementa después de este problema.

https://github.com/aspnet/EntityFramework/issues/3312

Con las versiones anteriores de EF, las propiedades de navegación virtual permitieron cargar lentamente las entidades relacionadas.

Supongo que cargar las propiedades de navegación por ahora solo se puede lograr con .Include(...)

EDITAR:

Hay varias formas de cargar entidades relacionadas que son compatibles con Core. Si está interesado: https://docs.microsoft.com/en-us/ef/core/querying/related-data


La palabra clave virtual nunca ha sido REQUERIDA ... Es opcional.

Que cambia

1. si declara su propiedad virtual:

Su propiedad virtual (por defecto) no se cargará de inmediato al consultar el objeto principal. Solo se recuperará de la base de datos si intenta acceder a ella o acceder a uno de sus componentes.

Y esto se llama carga diferida.

2. si lo declaras no virtual:

Su propiedad (por defecto) se cargará de inmediato junto con todas las demás propiedades en su entidad principal. Esto significa que su propiedad estará lista para acceder: ya ha sido recuperada. La entidad no tendrá que volver a consultar la base de datos porque accede a esta propiedad.

Esto se llama cargar ansiosamente.

Mi opinión :

Más a menudo elijo cargar con entusiasmo (no virtual) porque la mayoría de las veces, necesito que se usen todas las propiedades de cada entidad sin tener que volver a consultar (más rápido en el caso de que realmente quiera todo rápido) pero si accede a esta propiedad solo de vez en cuando (no está enumerando nada) y desea más a menudo solo el resto de la información, excepto ESTA, luego haga que sea virtual para que esta propiedad no ralentice el resto de la consulta solo por unos pocos accesos.

Espero que esto esté claro ...

Ejemplos:

Donde NO usaría virtual (con entusiasmo):

foreach(var line in query) { var v = line.NotVirtual; // I access the property for every line }

Donde usaría carga virtual o diferida:

foreach(var line in query) { if(line.ID == 509) // because of this condition var v = line.Virtual; // I access the property only once in a while }

una última cosa :

Si no consulta más de 1000 líneas de una base de datos, lo que elija no tendrá un gran efecto. Además, puede declarar estas propiedades virtuales y si desea probar al revés, solo tiene que hacer esto (Entidad 4.0):

context.LazyLoadingEnabled = false;

Se cancelará el efecto virtual.

Editar

Para versiones más nuevas de EF:

WhateverEntities db = new WhateverEntities() db.Configuration.LazyLoadingEnabled = false;


Las cosas han cambiado desde que se escribió la respuesta aceptada. En 2018, Lazy Loading ahora es compatible con Entity Framework Core 2.1 para dos enfoques diferentes.

La forma más simple de los dos es usar proxies, y esto requerirá que las propiedades deseadas se carguen perezosamente para definirse con virtual . Para citar desde la página vinculada:

La forma más sencilla de usar lazy-loading es instalando el paquete Microsoft.EntityFrameworkCore.Proxies y habilitándolo con una llamada a UseLazyLoadingProxies . [...] EF Core habilitará la carga diferida para cualquier propiedad de navegación que pueda ser anulada, es decir, debe ser virtual y estar en una clase de la que se pueda heredar.

Y aquí está el código de muestra proporcionado:

public class Blog { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Post> Posts { get; set; } } public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public virtual Blog Blog { get; set; } }

Hay otra forma de hacer Lazy Loading sin proxies, que es inyectar ILazyLoader en el constructor del tipo de datos. Esto se explica aquí .

En resumen, hay dos formas de realizar la carga diferida: con y sin proxies. virtual es necesario si y solo si desea admitir Lazy Loading con proxies. De lo contrario, no lo es.


virtual nunca fue requerido en EF. Solo era necesario si desea soporte de carga diferida.

Dado que EF Core aún no es compatible con la carga diferida , actualmente el virtual no tiene un significado especial. Lo haría cuando (y si) agregan soporte de carga diferida (hay un plan para hacerlo).

Actualización: a partir de EF Core 2.1, ahora se admite la carga diferida . Pero tan pronto como no agregue Microsoft.EntityFrameworkCore.Proxies paquete Microsoft.EntityFrameworkCore.Proxies y lo habilite a través de UseLazyLoadingProxies , la respuesta original aún se aplica.

Sin embargo, si lo hace, las cosas cambian totalmente debido a la falta de control de aceptación en la implementación inicial: requiere que todas sus propiedades de navegación sean virtual . Lo cual no tiene sentido para mí, será mejor que no lo uses hasta que se arregle. Si realmente necesita una carga diferida, utilice el enfoque alternativo de carga diferida sin proxies , en cuyo caso nuevamente virtual no importa.