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?

https://code.i-harness.com

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:

  1. 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;
  2. 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étodo include . Para ativar este tipo de carregamento:

    context.Configuration.LazyLoadingEnabled = false;
  3. Para o carregamento explícito É como o carregamento ansioso, mas usamos o método Load vez de include .

Então eu gostaria de saber:

  1. Se esse pequeno currículo é verdade?
  2. Se é verdade, qual é a diferença entre o carregamento rápido e o explícito?
  3. 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?
  4. 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 .





lazy-loading