Quais efeitos a palavra-chave virtual pode ter no Código POCO do Entity Framework 4.1 primeiro?

229

A virtualpalavra-chave tem efeito quando usada nas propriedades do EF Code First ?. Alguém pode descrever todas as suas ramificações em diferentes situações?

Por exemplo, eu sei que ele pode controlar o carregamento lento - se você usar a palavra-chave virtual em uma propriedade de relacionamento ICollection / um para muitos, ela será carregada lentamente por padrão, enquanto que se você deixar a palavra-chave virtual de fora, ela será estar ansiosamente carregado.

Que outros efeitos a virtualpalavra-chave pode ter no EF com entidades POCO ?. Devo torná-lo padrão para uso virtualem todas as minhas propriedades ou padrão para não usá-lo?

Scott Stafford
fonte

Respostas:

194

Até agora, eu conheço esses efeitos.

  • Carregamentovirtual lento : qualquer ICollection será carregado lentamente, a menos que você os marque especificamente.
  • Rastreamento de alterações mais eficiente . Se você atender a todos os requisitos a seguir, o rastreamento de alterações poderá usar um método mais eficiente, conectando suas propriedades virtuais. No link:

    Para obter proxies de rastreamento de alterações, a regra básica é que sua classe deve ser pública, não abstrata ou não selada. Sua classe também deve implementar getters / setters virtuais públicos para todas as propriedades persistentes. Por fim, você deve declarar propriedades de navegação de relacionamento baseadas em coleção como ICollection<T>apenas. Eles não podem ser uma implementação concreta ou outra interface derivada ICollection<T>(uma diferença do proxy de Carregamento Adiado)

Outro link útil que descreve isso são os Requisitos do MSDN para a criação de proxies POCO .

Scott Stafford
fonte
52
Não há outro motivo para tornar as propriedades virtuais. As propriedades de navegação são marcadas como virtuais para carregamento lento e as propriedades escalares são marcadas como virtuais para rastreamento de alterações.
Ladislav Mrnka
10
o que são propriedades de navegação e o que são propriedades escalares?
Abid Ali
9
@ AbidAli: Eu acredito que uma propriedade de navegação é uma chave estrangeira (um tipo de classe de entidade) ou uma relação de um para muitos (do tipo ICollection <>). Uma propriedade escalar é um tipo de base (int, string, ..) ou um ComplexType (que é apenas uma estrutura dos tipos de base).
Scott Stafford
2
O public virtual byte[] bigData { get; set; }carregamento é lento?
Agradeço o seu contato
9
bytes [] serão carregados avidamente, somente chaves estrangeiras podem ser preguiçosas. Se você não deseja buscar essa coluna, nunca busque o registro inteiro - apenas .Select(a=>new { fields you want }).
Scott Stafford
63

Essa palavra-chave virtual está relacionada ao tópico de carregamento de dados da estrutura da entidade (carregamento lento, carregamento rápido e carregamento explícito).

Você deve usar a palavra-chave virtual quando desejar carregar dados com carregamento lento.

carregamento lento é o processo pelo qual uma entidade ou coleção de entidades é carregada automaticamente do banco de dados na primeira vez que é acessada.

Por exemplo, ao usar a classe de entidade Blog definida abaixo, as Postagens relacionadas serão carregadas na primeira vez que a propriedade de navegação Postagens for acessada:

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

O carregamento lento da coleção Postagens pode ser desativado, tornando a propriedade Postagens não virtual.

se o carregamento lento estiver desativado, o carregamento da coleção Postagens ainda poderá ser alcançado usando o carregamento antecipado (usando o método Incluir) ou o carregamento explícito de entidades relacionadas (usando o método Load).

Carregando ansiosamente:

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

Carregando explicitamente:

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
fonte
1
Como evitar o problema de N + 1 ao usar o virtual (carregamento lento)? Por exemplo, context.Blogs.ToList (); então, ele não ingressará nas tabelas e executará a consulta de seleção tanto quanto o número de blogs.
Expert quer ser
1
@Expertwannabe Mesmo se você usar o carregamento lento, ainda poderá solicitar explicitamente o carregamento antecipado com uma chamada para Include().
Monsenhor