What effect(s) can the virtual keyword have in Entity Framework 4.1 POCO Code First?

Solution 1:

So far, I know of these effects.

  • Lazy Loading: Any virtual ICollections will be lazy-loaded unless you specifically mark them otherwise.
  • More efficient change tracking. If you meet all the following requirements then your change tracking can use a more efficient method by hooking your virtual properties. From the link:

    To get change tracking proxies, the basic rule is that your class must be public, non-abstract or non-sealed. Your class must also implement public virtual getters/setters for all properties that are persisted. Finally, you must declare collection based relationship navigation properties as ICollection<T> only. They cannot be a concrete implementation or another interface that derives from ICollection<T> (a difference from the Deferred Loading proxy)

Another useful link describing this is MSDN's Requirements for Creating POCO Proxies.

Solution 2:

This virtual keyword is related to the topic of loading data from entity framework (lazy loading, eager loading and explicit loading).

You should use virtual keyword, when you want to load data with lazy loading.

lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time it is accessed.

For example, when using the Blog entity class defined below, the related Posts will be loaded the first time the Posts navigation property is accessed:

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

Lazy loading of the Posts collection can be turned off by making the Posts property non-virtual.

if lazy loading is off, Loading of the Posts collection can still be achieved using eager loading (using Include method) or Explicitly loading related entities (using Load method).

Eagerly Loading:

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

Explicitly Loading:

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