problemas de desempenho Entity Framework adicionando criança para listar

votos
1

Eu estou trabalhando em um projeto onde nós estamos usando Entity Framework 6.1.3. Neste momento estamos enfrentando problemas muito grandes de desempenho ao adicionar um objeto filho para uma lista da entidade pai (ver exemplo de código abaixo).

Estamos usando carregamento lento, então o que eu observei é que tudo funciona bem até que nós chamamos _parent.Children.Add(child);uma vez que parece carregar todas as crianças a partir do banco de dados apenas para ser capaz de adicionar um novo. Uma vez que alguns dos nossos objetos pai tem cerca de 50.000 crianças, isso está atrasando esta chamada inserção simples por 7-8 segundos e às vezes até causando tempos de espera.

Para mim não faz muito sentido para Entity Framework para carregar todas as crianças apenas para adicionar um, então há uma maneira que eu posso evitar isso ou isso é um design falha Entity Framework e devemos encontrar uma solução alternativa?

Eu, obviamente, gostaria de encontrar uma solução para este e preferiria não ter que implementar consultas ADO puros para este problema.

Obrigado!

public class Parent 
{
    public Guid Id { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

public class Child
{
    public Guid Id { get; set; }
}

public class ParentAggregate
{
    private readonly Parent _state;

    public ParentAggregate(Parent state)
    {
        _state = state;
    }

    public void AddChild(Guid id)
    {
        var child = new Child { Id = id };
        _state.Children.Add(child);
    }
}
Publicado 19/12/2018 em 14:16
fonte usuário
Em outras línguas...                            


1 respostas

votos
2

Para mim não faz muito sentido para Entity Framework para carregar todas as crianças apenas para adicionar um

O carregamento lento ocorre na primeira vez que você acessar a propriedade de navegação através de sua getter . E o código de exemplo

_parent.Children.Add(child);

consiste em duas operações:

(1) recuperar a Childrenpropriedade (através da propriedade getter !):

var children = _parent.Children;

(2) executar alguma operação sobre ele (chamada Addmétodo, neste caso):

children.Add(child);

O carregamento lento ocorre por causa da operação (1). Como você pode ver, a EF tem nada a ver com isso, porque ele não tem controle sobre ele. E não há nenhuma maneira de saber o que você vai fazer com que o valor da propriedade - enumerá-lo, dê uma contagem ou uso Add, Removeetc. métodos.

Aqui estão algumas soluções.

Primeiro, por que usar o carregamento lento em tudo? Ele tem tantos efeitos colaterais e ineficiências, e todos eles podem ser facilmente resolvidos por EF fornecido fora do carregamento ansioso caixa através de Includemétodos. É por isso que, por padrão EF núcleo ( "o futuro da EF") não usar o carregamento lento por padrão e requer um pacote e procedimento especial para ativá-lo.

Em segundo lugar, se você insistir usando carregamento lento, então você tem duas opções a seguir:

(A) Desactivar o carregamento lento durante as modificações de dados (requer acesso ao / controlo da DbContextinstância):

dbContext.Configuration.LazyLoadingEnabled = false;
_parent.Children.Add(child);
dbContext.Configuration.LazyLoadingEnabled = true;

Isso também requer a propriedade de coleção para ser inicializado para evitar NRE.

(B) Use campo de apoio explícito e fornecer algum acesso direto a ele (para evitar desencadear a carga preguiçoso por acessor propriedade). Por exemplo:

public class Parent 
{
    public Guid Id { get; set; }

    private ICollection<Child> children;
    public virtual ICollection<Child> Children { get => children; set => children = value; }

    public void Add(Child child)
    {
        // use the backing field directly
        if (children == null) children = new HashSet<Child>();
        children.Add(child); 
    }
}
Respondeu 19/12/2018 em 15:20
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more