Why Use 'Virtual' for Class Properties in Entity Framework Model Definitions

Why use 'virtual' for class properties in Entity Framework model definitions?

It allows the Entity Framework to create a proxy around the virtual property so that the property can support lazy loading and more efficient change tracking. See What effect(s) can the virtual keyword have in Entity Framework 4.1 POCO Code First? for a more thorough discussion.

Edit to clarify "create a proxy around":
By "create a proxy around", I'm referring specifically to what the Entity Framework does. The Entity Framework requires your navigation properties to be marked as virtual so that lazy loading and efficient change tracking are supported. See Requirements for Creating POCO Proxies.

The Entity Framework uses inheritance to support this functionality, which is why it requires certain properties to be marked virtual in your base class POCOs. It literally creates new types that derive from your POCO types. So your POCO is acting as a base type for the Entity Framework's dynamically created subclasses. That's what I meant by "create a proxy around".

The dynamically created subclasses that the Entity Framework creates become apparent when using the Entity Framework at runtime, not at static compilation time. And only if you enable the Entity Framework's lazy loading or change tracking features. If you opt to never use the lazy loading or change tracking features of the Entity Framework (which is not the default), then you needn't declare any of your navigation properties as virtual. You are then responsible for loading those navigation properties yourself, either using what the Entity Framework refers to as "eager loading", or manually retrieving related types across multiple database queries. You can and should use lazy loading and change tracking features for your navigation properties in many scenarios though.

If you were to create a standalone class and mark properties as virtual, and simply construct and use instances of those classes in your own application, completely outside of the scope of the Entity Framework, then your virtual properties wouldn't gain you anything on their own.

Edit to describe why properties would be marked as virtual

Properties such as:

 public ICollection<RSVP> RSVPs { get; set; }

Are not fields and should not be thought of as such. These are called getters and setters, and at compilation time, they are converted into methods.

//Internally the code looks more like this:
public ICollection<RSVP> get_RSVPs()
{
return _RSVPs;
}

public void set_RSVPs(RSVP value)
{
_RSVPs = value;
}

private RSVP _RSVPs;

That's why they're marked as virtual for use in the Entity Framework; it allows the dynamically created classes to override the internally generated get and set functions. If your navigation property getter/setters are working for you in your Entity Framework usage, try revising them to just properties, recompile, and see if the Entity Framework is able to still function properly:

 public virtual ICollection<RSVP> RSVPs;

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

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.

Why Navigation Properties are virtual by default in EF

If you define your navigation property virtual, Entity Framework will at runtime create a new class (dynamic proxy) derived from your class and uses it instead of your original class. This new dynamically created class contains logic to load the navigation property when accessed for the first time. This is referred to as "lazy loading". It enables Entity Framework to avoid loading an entire tree of dependent objects which are not needed from the database.

In some circumstances, it is best to use "Eager Loading" instead, especially if you know that you will be interacting with related objects at some point.

Julie Lerman really is the authority on all things Entity Framework, and she explains this process very well in her MSDN Article Demystifying Entity Framework Strategies: Loading Related Data

Eager loading with Include is useful for scenarios where you know in advance that you want the related data for all of the core data being queried. But remember the two potential downsides. If you have too many Includes or navigation paths, the Entity Framework may generate a poorly performing query. And you should be careful about returning more related data than necessary thanks to the ease of coding with Include.

Lazy loading very conveniently retrieves related data behind the scenes for you in response to code that simply makes mention of that related data. It, too, makes coding simpler, but you should be conscientious about how much interaction it’s causing with the database. You may cause 40 trips to the database when only one or two were necessary.

If you are developing a Web Application where every communication with the server is a new context anyway, Lazy Loading will just create unnecessary overhead to maintain the dynamic class for related objects that will never be loaded. Many people will disable lazy loading in these scenarios. Ultimately, it's still best to evaluate your SQL queries which EF has built and determine which options will perform best for the scenario you are developing under.

Regarding the use virtual keyword for a property

Just like Patryk says, it's for being able to work smoothly with an ORM like NHibernate or Entity Framework. This ORM then builds proxy classes on top of those properties declared as virtual to enable lazy loading on them (getting all the navigation data).

Example:

public class User
{
public int ID { get; set; }
public virtual Role Role { get; set; }
}
public class Role
{
public int ID { get; set; }
public string Name { get; set; }
public virtual List<User> UsersInRole { get; set; }
}

When you get a user you will automatically get the associated Role. If you get a Role you automatically get all the Users in that Role.

Docs of Entity Framework: http://msdn.microsoft.com/en-us/data/jj679962

Entity Framework: Why virtual keyword used to declare properties in DbContext

The approach you want to achieve, lazy loading, means that the data provider, in your case Entity Framework, retrieves certain data at the time you need it. If, for example, you access all account types you probably don't need to access all account codes for these account types thus retrieving them from the database would be unnecessary.

If you had to write the SQL yourself, you would most likely write a plain select statement without joining the child relations:

SELECT * FROM AccountTypes;

Another use-case on the other hand might need access to this data so you would either end up with eagerly loading it which results in a join operation...

SELECT * FROM AccountTypes JOIN AccountCodes ON AccountCodes.AccountTypeId = AccountTypes.Id;

...or to rely on Entity Framework's lazy loading ability.

The latter case requires Entity Framework to do the following: First, selecting all account types and then, at the time your user-code accesses the account codes, emitting another select statement to retrieve the codes for the respective account type. To do so, Entity Framework needs a hook, i.e. it must know when you access the navigation property, which is in general impossible because this would need additional code in the getter of this property:

public class AccountType
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<AccountCode> AccountCodes
{
get { /* Load child data here */ }
set { /* ... */ }
}
}

Unfortunately Entity Framework is unable to alter the POCO class because it's your user-code, but what it can do is deriving from your class and overriding the property to inject it's magic. For this to work it creates what is called a proxy, i.e. it creates a class at runtime which derives from your POCO class, like:

public class AccountTypeProxy : AccountType
{
public override ICollection<AccountCode> AccountCodes
{
get { /* Load child data here */ }
set { /* ... */ }
}
}

So what you get when you retrieve the account types is actually a bunch of proxy instances, which you can confirm during debugging.

If you would not add the virtual keyword to the navigation property or if you sealed the class, Entity Framework could not override the property or could not derive from the class at all and thus lazy loading would not work.

Using Virtual on navigation properties

You use virtual properties on entities, so Entity Framework can create a proxy class at runtime that inherits from your entity and injects a stub into overridden properties. This stub does a database call when you access the property's getter from code.

Entity Framework Core does not support lazy loading (yet, and probably never will), so there's no reason for it to mark properties as virtual.

See also: Loading Related Data - Entity Framework Core 1.0.0 Documentation in the officical documentation, Lazy Loading · Issue #3797 · aspnet/EntityFramework · GitHub on GitHub and Why use 'virtual' for class properties in Entity Framework model definitions? here on Stack Overflow.

Use of virtual property in model class in mvc

If you really want to query data using self-made joins as you've shown in your example, you can safely delete Employee.Designation property.

Usually virtual properties are being used by Entity Framework for the lazy loading of related objects (process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed).

So using lazy loading your query can be written as

(from emp in dc.Employee
select new Class3
{
Employee = emp ,
Designation = emp.Designation,
}).Single();

and EntityFramework will make join by itself.

Side note: in this case it looks like your Class3 viewmodel almost duplicates Employee model so it looks redundant. But I suppose it could be some syntetic example, not real one.

navigation property should be virtual - not required in ef core?

virtual was never required in EF. It was needed only if you want lazy loading support.

Since Lazy loading is not yet supported by EF Core, currently virtual have no special meaning. It would when (and if) they add lazy loading support (there is a plan for doing so).

Update: Starting with EF Core 2.1, Lazy loading is now supported. But if you don't add Microsoft.EntityFrameworkCore.Proxies package and enable it via UseLazyLoadingProxies, the original answer still applies.

However if you do so, the thing's totally changed due to the lack of the opt-in control in the initial implementation - it requires all your navigation properties to be virtual. Which makes no sense to me, you'd better not use that until it gets fixed. If you really need lazy loading, use the alternative Lazy loading without proxies approach, in which case again virtual doesn't matter.



Related Topics



Leave a reply



Submit