Entity Framework – Queries com Expression<Func<T, bool>> e Func<T, bool>

Apesar dos dois tipos de dados compilarem normalmente quando os utilizamos em um query method, existe uma diferença no modo como as queries do Entity Framework são criadas quando utilizamos Expression<Func<T, bool>> e Func<T, bool>.

frajola

Quando utilizamos Expression<Func<T, bool>> o Entity Framework reconhece a expressão existente e a transforma em código SQL.

Mas, quando utilizamos Func<T, bool>, a função é compilada em Intermediate Language, e não é transformada em código SQL. Desta forma o filtro é feita em memória, logo após o load dos dados vindos do banco de dados.

Veja os dois métodos a seguir:

public IEnumerable<PostBlog> BadQuery(Func<PostBlog, bool> predicate) {

    using (var context = new DatabaseContext()) {

        var query = context.PostBlogs.Where(predicate);
                
        return query.ToList();
    }
}

public IEnumerable<PostBlog> GoodQuery(Expression<Func<PostBlog, bool>> predicate) {

    using (var context = new DatabaseContext()) {

        var query = context.PostBlogs.Where(predicate);
                
        return query.ToList();
    }
}

Ambos os métodos são bastante semelhantes, exceto pelo nome do método e o tipo de dados de seu parâmetro de entrada. Para este exemplo ambos os métodos são invocados com a mesma entrada, conforme apresentado abaixo:

var r1 = repository.BadQuery(p => p.Title == "entity framework");

var r2 = repository.GoodQuery(p => p.Title == "entity framework");

Mesmo com a mesma expressão lambda sendo utilizada em ambos os métodos, o código SQL gerado é diferente. O código gerado pelo Entity Framework para o método BadQuery é o código apresentado a baixo:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[Body] AS [Body]
    FROM [dbo].[PostBlogs] AS [Extent1]

… e o código SQL gerado para o método GoodQuery é o código apresentado a seguir:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[Body] AS [Body]
    FROM [dbo].[PostBlogs] AS [Extent1]
    WHERE (N'entity framework' = [Extent1].[Title]) 
	   AND ([Extent1].[Title] IS NOT NULL)

Note que o código SQL gerado para o método BadQuery não possui filtros, desta forma o EF consulta todos os registros e os filtra em memória. Enquanto que o método GoodQuery faz o filtro no código SQL (o que acarreta em um carregamento mais rápidos dos dados, além de economias de memória e processamento).

Por isso, revejam o modo como passam critérios dinâmicos para consultas do Entity Framework. É possível que a sua aplicação esteja consumindo mais recursos do que o necessário.

FH

About these ads

2 Responses to Entity Framework – Queries com Expression<Func<T, bool>> e Func<T, bool>

  1. Frederico disse:

    Muito boa a explicação.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Junte-se a 63 outros seguidores

%d blogueiros gostam disto: