c# – What is the difference between using virtual property or not in EF?

Question:

I have my models

public class Cliente
{
   public int Id {get;set;}
   public string Nome {get;set;}
}

e

public class Pedido
{
   public int Id {get;set;}
   public int ClienteId {get;set;}
   public virtual Cliente Cliente {get;set;}
}

Following the example above, what is the difference between

public virtual Cliente Cliente {get;set;}

e

public Cliente Cliente {get;set;}

I always notice that when using virtual my Client model is loaded

for example:

var pedido = dbo.Pedidos.Find(1);

If I try to access pedido.Cliente it is not null when it is virtual

What is the difference? How does the EF query ? Which form do I have more performance?

Answer:

Lazy Loading

Lazy Loading is the mechanism used by persistence frameworks to load information on demand. This mechanism makes entities lighter, as their associations are loaded only when the method that makes available the associative data is called. So when objects are returned by a query, the related objects are not loaded at the same time, instead they are loaded automatically when the navigation property is accessed.

The virtual modifier is used by EF to do Lazy Loading , which needs to create proxy instances that will be replaced in these virtual properties.

So you get the impression that this object is always loaded. But in fact he is not. A virtual property is only loaded via lazy loading when there is the first reference to that property. At that moment, the FE executes a new query in the database, requesting only the data below the hierarchy of the object of this property.

This can be seen when debugging your code in Visual Studio, the virtual property will be loaded at the exact moment you check its value.

The use of Lazy Loading can indeed bring performance problems. In your example, if you make a query that returns, say, 100 Pedidos , without explicitly loading customers (eager loading) , when referencing any Cliente information, for each different customer, a new query will be made in the database. So in that case you could have 100 new database queries.

var pedidos = db.Pedidos.ToList(); // não traz nenhuma informação de cliente
foreach (var pedido in pedidos) 
{
    var nome = pedido.Cliente.Nome; // aqui é feita a carga por Lazy Loading
}

Eager Loading

To avoid this effect you can inform that you want the EF to do Eager Loading of customers using an Include clause.

var pedidos = db.Pedidos.Include(m => m.Cliente).ToList(); // inclui cliente na query
foreach (var pedido in pedidos) 
{
    var nome = pedido.Cliente.Nome; // os dados de cliente já estão carregados
}

This way the SQL query will include the clients in the query.

In cases where we do not use the virtual modifier virtual we will only be able to access the Cliente via Eager Loading .

EF uses Lazy Loading by default on properties marked with the virtual modifier , otherwise it is turned off and so the object reference is null (except when we use eager loading via Include ).

It is possible to configure EF so that it does not work with Lazy Loading even when we have virtual properties.

public class MeuContexto : DbContext 
{ 
    public MeuContexto () 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}
Scroll to Top