Como fazer LOG no EF Core 5
O Entity Framework foi lançado há anos e tem sido muito usado em diversos tipos de projetos. Com a nova versão, o EF Core 5 temos um novo esquema de LOGs, e neste artigo vou mostrar como usá-lo em leitura de dados no SQL Server.
Sabemos que o DBA é o responsável pelos dados na empresa, é ele que aprova ou indica melhorias nas consultas. No entanto, como que o desenvolvedor vai saber se realmente está sendo executada um T-SQL no banco da melhor forma? Via de regra ele usa o profile do SQL Server para checar. Agora isto não é mais necessário porque o Log faz todas as funções.
No VS 2019, crie um novo projeto de Console Aplication em C#, conforme a figura a seguir.
No Target Framework, selecione .NET 5.0, que é a última versão que tenho instalada. Clique no botão Create para criar o projeto e aguarde.
A primeira coisa a fazer é adicionar os seguintes pacotes Nuget. Note que usarei o SQL Server e o Tools é para usarmos o Migrations.
<PackageReference Include=”Microsoft.EntityFrameworkCore” Version=”5.0.4" />
<PackageReference Include=”Microsoft.EntityFrameworkCore.SqlServer” Version=”5.0.4" />
<PackageReference Include=”Microsoft.EntityFrameworkCore.Tools” Version=”5.0.4">
Classes de Dados
Adicione um classe Models.cs contendo as duas classes Medico e Paciente, conforme o código a seguir. E estrutura diz que um médico contém vários pacientes (List<Paciente>).
Em seguida precisamos definir o contexto que irá criar o banco de dados dinamicamente e os DbSets para fazer o CRUD dinâmico das operações. No OnConfiguring estou informando que o banco de dados será no provider SQL Server (UseSqlServer do using Microsoft.EntityFrameworkCore) e o nome do banco ArtigoEFCoreLog contido na string de conexão. Caso queira usar outro provider, basta instalar o Nuget dele (Postgres, MySql, etc) e usar o respectivo Use(string de conexão).
Já no OnModelCreating como usaremos o Migrations, já defini alguns médicos e pacientes para serem inseridos no banco quando executar o Update-Database do Migrations.
Compile o projeto CTRL + SHIFT + B ou F6 e se estiver com sucesso, abra a janela do Packge Manager Console e digite:
Add-Migration SetupInicial
Isto irá compilar o projeto novamente, verificar quais as classes (DbSets) existentes no DbContext, gera a classe SetupInicial.cs dentro da pasta Migrations, contendo todo o script para criar as duas classes no banco. O foco do artigo não é o Migrations, portanto não vou explicar os bastidores.
Em seguida, nesta mesma tela execute o comando para criar o banco de dados efetivamente. Esta técnica chama-se Code-First, você cria as classes e o contexto antes do banco de dados.
Update-Database
LOG
Agora que já temos o banco criado com dados, no Program.cs adicione o código para listar os médicos e os pacientes separadamente.
Os comandos de Log são declarados no OnConfiguring do BancoContexto.cs, logo. O EnableSensitiveDataLogging diz a aplicação para habilitar logs de dados, exceções e informações das entidades.
O LogTo informa que as mensagens serão exibidas no Console.Writeline.
Pressione F5 para compilar e executar o projeto. Veja o resultado, é longo, mas vale destacar os passos onde mostra desde quando habilita o Log, Quale a versão do provider do BancoContexto, qual o DbSet envolvido, que tipo de consulta é criada, qual o select usado, o ExecuteReader, o DbCommand, dados de open e close da conexão com o banco, o Dispose dos objetos (Reader e BancoContexto.
LogLLevel — O log tem vários níveis de informações: Trace, Debug, Information, Warning, Error, Critical e None. Altere para exibir somente o LogLevel.Information.
Execute e veja o retorno, note as informações do BancoContexto, DbCommand (qual o T-SQL que o SQL Server executou), quanto tempo levou, e os parâmetros.
Caso queira exibir o LOG na janela de Output no Visual Studio, use os códigos a seguir. Nesta janela do DEbug são mostradas informações sobre Trace, quais DLLs foram chamadas, etc.
using System.Diagnostics;
optionsBuilder.LogTo(message => Debug.WriteLine(message));
Altere para exibir todas as chamadas somente do Contexto (Dispose e Initialize)
// registra todas as chamadas
optionsBuilder
.LogTo(Console.WriteLine, new[] { CoreEventId.ContextDisposed, CoreEventId.ContextInitialized });
Altere para chamadas apenas de Banco de dados, onde mostra o ExecuteReader, conexão com o banco e servidor, o Command T-SQL, tempo de execução e Close dos objetos.
// registra somente chamadas de banco de dados
optionsBuilder
.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Name });
Se quiser apenas informações sobre o Command executado, use:
// registra somente chamadas de consultas
optionsBuilder
.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name });
Agora, adicione um OrderBy e veja o resultado gerado no T-SQL.
Se você passar parâmetros para uma condição de filtro Where, por exemplo, veja o código e o resultado gerado. Note que o parâmetro é declarado no T-SQL.
Veja como fica o código e o resultado do LOG de uma operação de Insert em duas tabelas.
Conclusão:
Agora você não tem mais desculpas para verificar o que rola nos bastidores quando executa as consultas. Claro que isto vale para qualquer operação de CRUD no banco. Desta forma você conseguirá monitorar todas as chamadas no banco, conversar com o DBA para entender melhor como melhorar a performance.
Boa sorte e sucesso nos projetos, procure sempre estudar e se aperfeiçoar. Compartilhe códigos e conhecimentos com as pessoas :)
Renato Haddad
Microsoft Most Valuable Professional
rehaddad@msn.com
Repositório do código fonte:
rehaddad/ArtigoLogEFCore5: Artigo sobre LOG do EF Core 5 (github.com)