Quali effetti possono avere prima la parola chiave virtuale nel codice POCO di Entity Framework 4.1?


229

La virtualparola chiave ha un effetto se utilizzata sulle proprietà in EF Code First ?. Qualcuno può descrivere tutte le sue ramificazioni in diverse situazioni?

Ad esempio, so che può controllare il caricamento lazy : se si utilizza la parola chiave virtuale su una proprietà relazione ICollection / one-to-many, verrà caricata lazy di default, mentre se si lascia fuori la parola chiave virtuale, essere impaziente.

Quali altri effetti può virtualavere la parola chiave in EF con entità POCO ?. Devo renderlo predefinito per l'uso virtualsu tutte le mie proprietà, o predefinito per non usarlo?

Risposte:


194

Finora, conosco questi effetti.

  • Caricamentovirtual lento : eventuali ICollezioni verranno caricati lentamente se non diversamente specificato.
  • Tracciamento delle modifiche più efficiente . Se si soddisfano tutti i seguenti requisiti, il rilevamento delle modifiche può utilizzare un metodo più efficiente collegando le proprietà virtuali. Dal link:

    Per ottenere i proxy di rilevamento delle modifiche, la regola di base è che la tua classe deve essere pubblica, non astratta o non sigillata. La tua classe deve inoltre implementare getter / setter virtuali pubblici per tutte le proprietà persistenti. Infine, è necessario dichiarare ICollection<T>solo le proprietà di navigazione delle relazioni basate sulla raccolta . Non possono essere un'implementazione concreta o un'altra interfaccia da cui deriva ICollection<T>(una differenza dal proxy di caricamento differito)

Un altro collegamento utile che descrive questo è i requisiti di MSDN per la creazione di proxy POCO .


52
Non vi sono altri motivi per rendere le proprietà virtuali. Le proprietà di navigazione sono contrassegnate come virtuali per il caricamento lento e le proprietà scalari sono contrassegnate come virtuali per il rilevamento delle modifiche.
Ladislav Mrnka,

10
quali sono le proprietà di navigazione e quali sono le proprietà scalari?
Abid Ali

9
@AbidAli: credo che una proprietà di navigazione sia una chiave esterna (un tipo di classe di entità) o una relazione uno a molti (di tipo ICollection <>). Una proprietà scalare è un tipo di base (int, string, ..) o un ComplexType (che è solo una struttura di tipi di base).
Scott Stafford,

2
Il public virtual byte[] bigData { get; set; }caricamento " " è lento?
AechoLiu,

9
i byte [] verranno caricati con impazienza, solo le chiavi esterne possono essere pigre. Se non vuoi recuperare quella colonna, non recuperare mai l'intero record - solo .Select(a=>new { fields you want }).
Scott Stafford,

63

Questa parola chiave virtuale è correlata all'argomento del caricamento dei dati dal framework di entità (caricamento lazy, caricamento desideroso e caricamento esplicito).

È necessario utilizzare una parola chiave virtuale quando si desidera caricare dati con caricamento lento.

il caricamento lento è il processo mediante il quale un'entità o una raccolta di entità viene caricata automaticamente dal database al primo accesso.

Ad esempio, quando si utilizza la classe di entità Blog definita di seguito, i Post correlati verranno caricati al primo accesso alla proprietà di navigazione Posts:

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

Il caricamento lento della raccolta Posts può essere disattivato rendendo la proprietà Posts non virtuale.

se il caricamento lento è disattivato, il caricamento della raccolta Messaggi può ancora essere ottenuto utilizzando il caricamento desideroso (utilizzando il metodo Includi) o il caricamento esplicito di entità correlate (usando il metodo Carica).

Caricamento ansioso:

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

Caricamento esplicito:

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

1
Come evitare il problema N + 1 quando si utilizza virtuale (caricamento lento)? Ad esempio, context.Blogs.ToList (); quindi non unirà le tabelle e eseguirà la query di selezione fino al numero di blog.
esperto vuole essere il

1
@Expertwannabe Anche se si utilizza il caricamento lento, è comunque possibile richiedere esplicitamente il caricamento desideroso con una chiamata a Include().
Mons.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.