¿Qué efecto (s) puede tener la palabra clave virtual en Entity Framework 4.1 POCO Code First?

229

Hace el virtual palabra clave tiene un efecto cuando se usa en las propiedades de EF Code First ?. ¿Alguien puede describir todas sus ramificaciones en diferentes situaciones?

Por ejemplo, sé que puede controlar la carga diferida : si usa la palabra clave virtual en una propiedad de relación ICollection / uno a muchos, se cargará de forma diferida de forma predeterminada, mientras que si deja la palabra clave virtual fuera, estar ansioso de cargar.

¿Qué otros efectos puede virtualtener la palabra clave en EF con entidades POCO? ¿Debo usarlo de manera predeterminada virtualen todas mis propiedades o no usarlo de manera predeterminada?

Scott Stafford
fuente

Respuestas:

194

Hasta ahora, sé de estos efectos.

  • Cargavirtual diferida : cualquier ICollections se cargará diferidamente a menos que las marque específicamente de otra manera.
  • Seguimiento de cambios más eficiente . Si cumple con todos los siguientes requisitos, su seguimiento de cambios puede usar un método más eficiente al conectar sus propiedades virtuales. Desde el enlace:

    Para obtener proxies de seguimiento de cambios, la regla básica es que su clase debe ser pública, no abstracta o no sellada. Su clase también debe implementar getters / setters virtuales públicos para todas las propiedades que persisten. Finalmente, debe declarar las propiedades de navegación de relación basadas en la colección como ICollection<T>solo. No pueden ser una implementación concreta u otra interfaz derivada de ICollection<T>(una diferencia del proxy de carga diferida)

Otro enlace útil que describe esto son los Requisitos de MSDN para Crear Proxies POCO .

Scott Stafford
fuente
52
No hay otra razón para hacer que las propiedades sean virtuales. Las propiedades de navegación se marcan como virtuales para la carga diferida y las propiedades escalares se marcan como virtuales para el seguimiento de cambios.
Ladislav Mrnka
10
¿Qué son las propiedades de navegación y qué son las propiedades escalares?
Abid Ali
99
@AbidAli: Creo que una propiedad de navegación es una clave foránea (un tipo de clase de entidad) o una relación de uno a muchos (de tipo ICollection <>). Una propiedad escalar es un tipo base (int, string, ..) o ComplexType (que es solo una estructura de tipos base).
Scott Stafford
2
¿La public virtual byte[] bigData { get; set; }carga " " es lenta?
AechoLiu
99
bytes [] se cargarán ansiosamente, solo las claves externas pueden ser perezosas. Si no desea recuperar esa columna, nunca recupere todo el registro, solo .Select(a=>new { fields you want }).
Scott Stafford
63

Esta palabra clave virtual está relacionada con el tema de cargar datos desde el marco de la entidad (carga diferida, carga ansiosa y carga explícita).

Debe usar una palabra clave virtual cuando desee cargar datos con carga diferida.

la carga diferida es el proceso mediante el cual una entidad o colección de entidades se carga automáticamente desde la base de datos la primera vez que se accede a ella.

Por ejemplo, cuando se usa la clase de entidad Blog definida a continuación, las Publicaciones relacionadas se cargarán la primera vez que se acceda a la propiedad de navegación Publicaciones:

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; }  
}

La carga diferida de la colección Posts se puede desactivar haciendo que la propiedad Posts no sea virtual.

si la carga diferida está desactivada, la carga de la colección de publicaciones aún se puede lograr usando carga ansiosa (usando el método Incluir) o cargando explícitamente entidades relacionadas (usando el método Load).

Cargando ansiosamente:

using (var context = new BloggingContext()) 
{ 
    // Load all blogs and related posts 
    var blogs1 = context.Blogs 
                          .Include(b => b.Posts) 
                          .ToList(); 
}

Cargando explícitamente:

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 

    // Load the posts related to a given blog 
    context.Entry(blog).Collection(p => p.Posts).Load(); 
}
Parsa
fuente
1
¿Cómo evitar el problema N + 1 cuando se usa virtual (carga diferida)? Por ejemplo, context.Blogs.ToList (); entonces no unirá tablas y ejecutará la consulta de selección tanto como el número de blogs.
Experto quiere ser
1
@Expertwannabe Incluso si usa la carga diferida, aún puede solicitar explícitamente la carga ansiosa con una llamada a Include().
Monseñor