Welche Auswirkungen kann das virtuelle Schlüsselwort in Entity Framework 4.1 POCO Code First haben?

229

Hat das virtualSchlüsselwort eine Auswirkung auf die Eigenschaften in EF Code First?. Kann jemand alle seine Auswirkungen in verschiedenen Situationen beschreiben?

Ich weiß zum Beispiel, dass es das verzögerte Laden steuern kann. Wenn Sie das virtuelle Schlüsselwort für eine ICollection / Eins-zu-Viele-Beziehungseigenschaft verwenden, wird es standardmäßig verzögert geladen. Wenn Sie das virtuelle Schlüsselwort weglassen, wird es dies auch tun eifrig geladen sein.

Welche anderen Auswirkungen kann ein virtualKeyword in EF mit POCO-Entitäten haben? Sollte ich es standardmäßig für virtualalle meine Eigenschaften verwenden oder standardmäßig nicht verwenden?

Scott Stafford
quelle

Antworten:

194

Bisher kenne ich diese Effekte.

  • Lazy Loading : Alle virtualICollections werden faul geladen, sofern Sie sie nicht ausdrücklich anders markieren.
  • Effizientere Änderungsverfolgung . Wenn Sie alle folgenden Anforderungen erfüllen, kann Ihre Änderungsverfolgung eine effizientere Methode verwenden, indem Sie Ihre virtuellen Eigenschaften verknüpfen. Über den Link:

    Die Grundregel lautet, dass Ihre Klasse öffentlich, nicht abstrakt oder nicht versiegelt sein muss, um Proxys für die Änderungsverfolgung zu erhalten. Ihre Klasse muss auch öffentliche virtuelle Getter / Setter für alle Eigenschaften implementieren, die beibehalten werden. Schließlich müssen Sie nur sammlungsbasierte Beziehungsnavigationseigenschaften als ICollection<T>nur deklarieren . Sie können keine konkrete Implementierung oder eine andere Schnittstelle sein, von der abgeleitet wird ICollection<T>(ein Unterschied zum Proxy für verzögertes Laden).

Ein weiterer nützlicher Link, der dies beschreibt, sind die Anforderungen von MSDN zum Erstellen von POCO-Proxies .

Scott Stafford
quelle
52
Es gibt keinen anderen Grund, Eigenschaften virtuell zu machen. Navigationseigenschaften werden für verzögertes Laden als virtuell und Skalareigenschaften für Änderungsverfolgung als virtuell markiert.
Ladislav Mrnka
10
Was sind Navigationseigenschaften und was sind Skalareigenschaften?
Abid Ali
9
@AbidAli: Ich glaube, eine Navigationseigenschaft ist ein Fremdschlüssel (ein Entitätsklassentyp) oder eine Eins-zu-Viele-Beziehung (vom Typ ICollection <>). Eine skalare Eigenschaft ist ein Basistyp (int, string, ..) oder ein ComplexType (der nur eine Struktur von Basistypen ist).
Scott Stafford
2
Ist " public virtual byte[] bigData { get; set; }" faul laden?
AechoLiu
9
Bytes [] werden eifrig geladen, nur Fremdschlüssel können faul sein. Wenn Sie diese Spalte nicht abrufen möchten, rufen Sie niemals den gesamten Datensatz ab - nur .Select(a=>new { fields you want }).
Scott Stafford
63

Dieses virtuelle Schlüsselwort bezieht sich auf das Thema Laden von Daten aus dem Entity Framework (verzögertes Laden, eifriges Laden und explizites Laden).

Sie sollten das virtuelle Schlüsselwort verwenden, wenn Sie Daten mit verzögertem Laden laden möchten.

Lazy Loading ist der Prozess, bei dem eine Entität oder Sammlung von Entitäten beim ersten Zugriff automatisch aus der Datenbank geladen wird.

Wenn Sie beispielsweise die unten definierte Blog-Entitätsklasse verwenden, werden die zugehörigen Posts beim ersten Zugriff auf die Navigationseigenschaft "Posts" geladen:

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

Das verzögerte Laden der Posts-Sammlung kann deaktiviert werden, indem die Posts-Eigenschaft nicht virtuell gemacht wird.

Wenn das verzögerte Laden deaktiviert ist, kann das Laden der Posts-Sammlung weiterhin durch eifriges Laden (mithilfe der Include-Methode) oder explizites Laden verwandter Entitäten (mithilfe der Load-Methode) erreicht werden.

Eifriges Laden:

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

Explizites Laden:

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
quelle
1
Wie vermeide ich N + 1-Probleme bei der Verwendung von Virtual (Lazy-Loading)? Zum Beispiel context.Blogs.ToList (); Dann werden keine Tabellen verknüpft, und die Auswahlabfrage wird so oft ausgeführt wie die Anzahl der Blogs.
Experte will
1
@Expertwannabe Auch wenn Sie Lazy-Loading verwenden, können Sie mit einem Anruf bei explizit das eifrige Laden anfordern Include().
Monsignore