c# - Carregamento ansioso, lento e explícito no EF6
entity-framework orm (2)
Se esse pequeno currículo é verdade?
Sim.
Se é verdade, qual é a diferença entre o carregamento rápido e o explícito?
Carregamento rápido
é o oposto do
carregamento
lento
, mas o
carregamento
explícito
é semelhante ao
carregamento lento
,
exceto que:
você recupera explicitamente os dados relacionados no código;
isso não acontece automaticamente quando você acessa uma propriedade de navegação.
Você carrega dados relacionados manualmente obtendo a entrada do gerenciador de estado do objeto para uma entidade e chamando o método
Collection.Load
para coleções ou o método
Reference.Load
para propriedades que contêm uma única entidade.
De techblog :
Carregamento ansioso:
Carregamento rápido é o oposto do carregamento lento, que é: O processo de carregar um conjunto específico de objetos relacionados junto com os objetos explicitamente solicitados na consulta.
Carregamento explícito:
O carregamento explícito é definido como: quando os objetos são retornados por uma consulta, os objetos relacionados não são carregados ao mesmo tempo. Por padrão, eles não são carregados até que sejam explicitamente solicitados usando o método Load em uma propriedade de navegação.
E:
Se eu usar o carregamento lento e eu chamo por exemplo
dpc_gestion.dpc_participant
, as propriedades de navegação são carregadas? Ou receberei uma exceção?
Você não recebe nenhuma exceção e as propriedades de navegação devem ser carregadas.
Existe um caso em que o carregamento antecipado ou o carregamento explícito foram melhores do que o carregamento lento no desempenho e na capacidade de resposta?
O carregamento ansioso é geralmente mais eficiente quando você precisa dos dados relacionados para todas as linhas recuperadas da tabela principal. E também quando as relações não são muito, um carregamento ávido será uma boa prática para reduzir mais consultas no servidor. Mas quando você sabe que você não precisa de uma propriedade instantaneamente, então o carregamento preguiçoso talvez seja uma boa escolha. E também o carregamento antecipado é uma boa opção em uma situação em que o contexto do banco de dados seria descartado e o carregamento lento não poderia mais ocorrer. Por exemplo, considere o seguinte:
public List<Auction> GetAuctions()
{
using (DataContext db = new DataContext())
{
return db.Auctions.ToList();
}
}
Depois de chamar esse método, você não pode carregar a entidade relacionada preguiçosamente porque o
db
é descartado e, portanto, o
carregamento ansioso
seria uma escolha melhor aqui.
Só mais uma coisa a notar é: O carregamento preguiçoso produzirá várias solicitações de SQL enquanto estiver carregando dados de carregamento com uma única solicitação. O carregamento antecipado também é uma boa opção para resolver o problema de seleção n + 1 nos ORMs. Dê uma olhada neste post: Qual é o n + 1 seleciona o problema?
Eu li este tutorial e este article mas não entendo exatamente o uso de cada tipo de carregamento.
Eu explico
Eu tenho esse POCO:
public partial class dpc_gestion
{
public dpc_gestion()
{
this.ass_reunion_participant = new HashSet<ass_reunion_participant>();
this.dpc_participant = new HashSet<dpc_participant>();
this.dpc_reunion = new HashSet<dpc_reunion>();
}
public int dpc_id_pk { get; set; }
public Nullable<int> dpc_id_gdp_fk { get; set; }
public Nullable<int> dpc_id_theme { get; set; }
public int dpc_id_animateur_fk { get; set; }
public Nullable<System.DateTime> dpc_date_creation { get; set; }
public Nullable<System.DateTime> dpc_date_fin { get; set; }
public Nullable<System.DateTime> dpc_date_engag_anim { get; set; }
public Nullable<bool> dpc_flg_let_engag_anim { get; set; }
public Nullable<bool> dpc_flg_fsoins_anim { get; set; }
public virtual ICollection<ass_reunion_participant> ass_reunion_participant { get; set; }
public virtual theme_dpc theme_dpc { get; set; }
public virtual gdp_groupe_de_pair gdp_groupe_de_pair { get; set; }
public virtual ICollection<dpc_participant> dpc_participant { get; set; }
public virtual ICollection<dpc_reunion> dpc_reunion { get; set; }
}
Eu entendi isso:
-
Para carregamento preguiçoso : como a carga é preguiçosa, se eu chamar o dbset
dpc_gestion
todas as propriedades de navegação não serão carregadas. Esse tipo de carregamento é o melhor em desempenho e capacidade de resposta. Está habilitado por padrão e se eu gostaria de reativá-lo eu tenho que definir:context.Configuration.ProxyCreationEnabled = true; context.Configuration.LazyLoadingEnabled = true;
-
Para o carregamento ansioso Não é preguiçoso: ele carregou todas as propriedades de navegação quando eu carrego
dpc_gestion
. As propriedades de navegação podem ser carregadas usando o métodoinclude
. Para ativar este tipo de carregamento:context.Configuration.LazyLoadingEnabled = false;
-
Para o carregamento explícito É como o carregamento ansioso, mas usamos o método
Load
vez deinclude
.
Então eu gostaria de saber:
- Se esse pequeno currículo é verdade?
- Se é verdade, qual é a diferença entre o carregamento rápido e o explícito?
-
Se eu usar o
carregamento lento
e eu chamo por exemplo
dpc_gestion.dpc_participant
, as propriedades de navegação são carregadas? Ou receberei uma exceção? - Existe um caso em que o carregamento antecipado ou o carregamento explícito foram melhores do que o carregamento lento no desempenho e na capacidade de resposta?
obrigado
Aqui você aprenderá a carregar entidades relacionadas em um gráfico de entidade explicitamente. O carregamento explícito é válido tanto no EF 6 quanto no EF Core.
Mesmo com o carregamento lento desativado (no EF 6), ainda é possível carregar preguiçosamente entidades relacionadas, mas isso deve ser feito com uma chamada explícita.
Use o método
Load()
para carregar entidades relacionadas explicitamente.
Considere o seguinte exemplo.
using (var context = new SchoolContext())
{
var student = context.Students
.Where(s => s.FirstName == "Bill")
.FirstOrDefault<Student>();
context.Entry(student).Reference(s => s.StudentAddress).Load();
// loads StudentAddress
context.Entry(student).Collection(s => s.StudentCourses).Load();
// loads Courses collection
}
No exemplo acima,
context.Entry(student).Reference(s => s.StudentAddress).Load()
carrega a entidade
StudentAddress
.
O método
Reference()
é usado para obter um objeto da propriedade de navegação de referência especificada e o método
Load()
carrega explicitamente.
Da mesma forma,
context.Entry(student).Collection(s => s.Courses).Load()
carrega a propriedade de navegação de coleção Courses da entidade Student.
O método
Collection()
obtém um objeto que representa a propriedade de navegação da coleção.
O método
Load()
executa a consulta SQL no banco de dados para obter os dados e preencher a referência especificada ou propriedade de coleção na memória, conforme mostrado abaixo.
Consulta ():
Você também pode escrever consultas LINQ para Entidades para filtrar os dados relacionados antes do carregamento.
O método Query () nos permite escrever mais consultas LINQ para as entidades relacionadas para filtrar os dados relacionados.
using (var context = new SchoolContext())
{
var student = context.Students
.Where(s => s.FirstName == "Bill")
.FirstOrDefault<Student>();
context.Entry(student)
.Collection(s => s.StudentCourses)
.Query()
.Where(sc => sc.CourseName == "Maths")
.FirstOrDefault();
}
No exemplo acima,
.Collection(s => s.StudentCourses).Query()
nos permite escrever mais consultas para a entidade
StudentCourses
.