Pontos de dados

Ferramentas legais (e gratuitas) para o Entity Framework

Julie Lerman

Julie LermanAgora que o Entity Framework é um software livre, a comunidade de desenvolvimento pode contribuir com sua codificação em entityframework.codeplex.com. Mas não limite-se a procurar por ferramentas e extensões. Há outras ótimas ferramentas, comerciais e para a comunidade, que podem ajudar a obter mais com o Entity Framework. Nesta coluna, irei destacar algumas dessas ferramentas e extensões fornecidas com a comunidade. Elas são todas gratuitas e estão disponíveis através da Galeria do Visual Studio (para extensões IDE) ou NuGet (para bibliotecas de códigos). Há até alguns membros da equipe do Entity Framework que são projetos preferidos e externos aos bits oficiais.

EntityFramework Reverse POCO Code First Generator

Ainda há muitos amigos pensando que o fluxo de trabalho Database First é a única forma de criar um modelo para o Entity Framework para um banco de dados existente. Esse fluxo de trabalho particular cria um arquivo EDMX, que permite interagir com seu modelo em um designer. Usar o designer também significa que você depende de um gerador de código para criar suas classes de entidade. Mas é possível usar o EF Code First com um banco de dados pré-existente graças às ferramentas de engenharia inversa. Agora há três formas de realizar isso. Minha favorita é este modelo: EntityFramework Reverse POCO Code First Generator por Simon Hughes (efreversepoco.codeplex.com). Para ser justo, as outras duas são ferramentas criadas pela Microsoft que também utilizei bastante. Uma é um recurso do EF Power Tools Beta, que você pode ver em ação na minha postagem do blog de maio de 2011 em bit.ly/1ky2SAJ. A outra é uma melhoria no Visual Studio EF Designer que foi no lançamento do Entity Framework 6.1 Tools para Visual Studio. O EF Designer agora inclui uma forma visual de criar POCOs de um banco de dados existente e resolve um problema que me angustiou por longo tempo fornecendo a capacidade de selecionar quais tabelas incluir em um modelo. Eu demonstrei este recurso na minha postagem do blog de fevereiro de 2014 em bit.ly/1rOqUv4.

O modelo de Hughes foi lançado no CodePlex em outubro de 2012 e tinha a capacidade de selecionar subconjuntos de um banco de dados desde o início. De fato, a ferramenta parece fornecer todos os recursos que esperava serem adicionados ou melhorados no EF Power Tools e no mais recente EF6.1 Designer. Não sou o único a pensar desta forma: Conforme escrevo esta coluna, houve cerca de 77.000 downloads do EntityFramework Reverse POCO Code First Generator.

Você pode instalar o modelo através do recurso Extensões e Atualizações do Visual Studio e tem acesso offline a ele para futuros projetos ou pode usar diretamente na Web sempre que desejar gerar POCOs de um banco de dados. Antes de adicionar o modelo, você deve adicionar o Entity Framework para seu projeto e especificar explicitamente a cadeia de conexão do banco de dados em seu arquivo de configuração, porque o modelo confia nele. Quando você tem o EF e sua cadeia de conexão, inicia o modelo adicionando um novo item a um projeto no Visual Studio. Se você instalou o modelo, encontrará em Instalado. Caso contrário, abra a seção Online. Observe que eu não filtrei os modelos na Figura 1, mas o EntityFramework Reverse POCO Code First Generator está no topo da lista classificada pelos itens Mais Populares. Eu fiquei certamente impressionado por essa posição.

Obter o EntityFramework Reverse POCO Code First Generator
Figura 1 Obter o EntityFramework Reverse POCO Code First Generator

Selecionar este item resulta em um novo arquivo de modelo database.tt no seu projeto. O modelo tem uma série de configurações com as configurações padrões já aplicadas. Você pode ver um corte do arquivo de modelo na Figura 2, que mostra algumas das configurações mais simples que podem ser usadas para impactar o código gerado. A configuração ElementsToGenerate permite controlar quais tipos de classes são geradas (POCOs, contexto, configurações fluentes, UnitOfWork). Um dos benefícios desta configuração é que você pode gerar itens diferentes para projetos diferentes. É possível controlar os namespaces e como os tipos são nomeados. É possível gerar algumas classes do Windows Communication Foundation (WCF) básicas e mais. As configurações também permitem especificar quais tabelas do banco de dados devem ser incluídas/excluídas usando Regexes para especificar os padrões da tabela os ou nomes de exibição. Especificar objetos tem sido um recurso importante para mim. No entanto, agora que o EF6.1 Designer suporta a seleção visual de objetos do banco de dados para a criação de um modelo Code First, descobri que especificar os nomes de objeto no arquivo .tt é um pouco mais difícil em comparação.

Uma seção do arquivo de configuração do EntityFramework Reverse POCO Generator
Figura 2 Uma seção do arquivo de configuração do EntityFramework Reverse POCO Generator

Outra vantagem significativa que o Reverse POCO Code First Generator tinha sobre o recurso de engenharia inversa do EF Power Tools era o desempenho. No entanto, o novo EF6.1 Designer acelera a geração de código dramaticamente, portanto, não é mais um fator determinante para mim. Independentemente, o Reverse POCO Code First Generator tem vários recursos interessantes (como a inclusão de valores padrões para colunas como valores padrões para propriedades) e formas de personalizar como as classes são geradas (como especificar qual tipo de coleção deve ser usada para as propriedades de navegação) que eu ainda gosto. Eu gostaria apenas de mesclar com o EF Designer.

Há tanta coisa neste modelo que, em vez de listar todos os seus recursos aqui, irei indicar para a documentação e o vídeo de demonstração de 30 minutos (reversepoco.com) para que você possa obter um excelente começo sobre o uso deste modelo. Você também verá que Hughes tem aceite contribuições para o projeto no CodePlex. Uma observação importante para lembrar é que o EntityFramework Reverse POCO Code First Generator atualmente trabalha com SQL Server e SQL Server CE. O EF6.1 Designer trabalha com estes bancos de dados e outros provedores do banco de dados que foram atualizados para trabalhar com o EF6.1. Eu soube que o próximo grande lançamento (v3) do gerador de Hughes poderá inverter a engenharia de outros bancos de dados, como Oracle, MySQL e assim por diante, da mesma forma que o EF6.1 Designer.

Utilitários do Entity Framework

A próxima biblioteca que estou destacando é mantida por Mikael Eliasson no GitHub (bit.ly/UeWHGW). Você pode obter utilitários em seus projetos pesquisando por EFUtilities no NuGet.

Este conjunto de utilitários focaliza no desempenho e adiciona funcionalidade para algo perdido há muito tempo pelos desenvolvedores do Entity Framework: a capacidade de realizar operações em massa—inserir, atualizar e excluir—no banco de dados. A classe EFBulkOperation nestes utilitários funciona com DbContext, portanto, você pode usá-la com o ObjectContext. Embora vários desenvolvedores tenham analisado o problema, eu conheço Mikael por algum tempo, portanto, naturalmente preferi sua oferta. Também há uma discussão no site CodePlex para o Entity Framework sobre as melhores abordagens para obter operações em massa no API nativo.

O utilitário permite gravar consultas LINQ na classe EFBulk­Operation para executar a operação relevante. Como um teste, eu criei um modelo (usando a ferramenta EntityFramework Reverse POCO Code First Generator apenas mencionada) pelo banco de dados AdventureWorks2012. No meu código, eu criei uma lista de 1.000 instâncias do tipo BusinessEntity:

var entityList = new List<BusinessEntity>();
for (int i = 0; i < 1000; i++)
{
  entityList.Add(new BusinessEntity{});
}

Eu inseri usando o código do Entity Framework padrão e chamei SaveChanges:

using (var context = new AWModel()) {
  context.BusinessEntities.AddRange(entityList);
  context.SaveChanges();
}

Isso fez com que 1.000 instruções insert individuais fossem enviadas para o meu banco de dados do SQL Server e a operação completa levou uma média de 6 segundos por várias execuções repetidas. Eu removi o tempo de aquecimento do EF deste tempo.

Usei a classe EFBatchOperation para inserir os mesmos 1.000 objetos BusinessEntity:

using (var context2 = new AWModel()) {
  EFBatchOperation.For(context2, 
    context2.BusinessEntities).InsertAll(entityList);
}

A execução média foi de cerca de 12 milissegundos.

Lembre-se de que no código EF padrão, eu precisei adicionar todas as instâncias no contexto para que o rastreador de mudança possa determinar o que o SQL precisa para ser enviado ao servidor. Por outro lado, a classe EFBatchOperation não confia no rastreador de mudança do EF para compilar o SQL. Em vez disso, cria um DataReader que é uma classe no EFUtilities e transmite para o banco de dados usando a classe .NET SqlBulkCopy introduzido anteriormente no ADO.NET 2.0. Fiquei feliz em ver isso porque sempre foi o caminho que recomendei para resolver este problema. Portanto, não apenas este método não força o contexto a rastrear 1.000 entidades como também envia um único comando para o banco de dados junto com o fluxo binário de dados a ser inserido. O SQL Profiler não exibirá o fluxo, portanto, tudo que vejo no SQL Profiler como resultado do método EFBatchoperation.InsertAll é este único comando:

insert bulk BusinessEntity
  ([rowguid] UniqueIdentifier,
  [ModifiedDate] DateTime)

Uma boa proteção aqui é que se o provedor de banco de dados usado não tem um método em massa, o utilitário reverterá para a forma padrão EF de lidar com a solicitação. Neste caso, isso significaria enviar 1.000 comandos insert para o banco de dados.

O EFBatchOperation também tem métodos para realizar atualizações e exclusões em massa, e o bom sobre cada um deles é que você não precisará carregar as entidades na memória ou o contexto antecipadamente como faria com o EF. Em vez disso, aqui está um exemplo de como você exclui uma seleção de linhas do banco de dados usando EFBatchOperation:

EFBatchOperation.For(context, context.BusinessEntityContacts).Where(
  p => p.ContactTypeId == 11).Delete();

Envia o SQL relevante para o banco de dados:

DELETE FROM [Person].[BusinessEntityContact] WHERE 11 = [ContactTypeID]

Os comandos de operação em massa já fornecem ganhos de desempenho significativos e agora a Eliasson está trabalhando na substituição do método DbContext.Include para melhorar o desempenho do carregamento antecipado. Em vez de nivelar os dados e gastar recursos em muitos dados redundantes nos resultados, o objetivo do método nos Utilitários EF é "carregar cada coleta Incluída como uma consulta separada em vez de corrigir manualmente as relações. O objetivo também é fornecer filtragem de coletas secundárias, classificação e, se possível, paginamento". É possível ler mais sobre este recurso e verificar seu progresso em bit.ly/1hBsGf5. Não ignore o arquivo readme.md deste projeto.

Entity Framework 6 Contrib

Entity Framework 6 Contrib é um projeto no CodePlex do Microsoft MVP Unai Zorrilla (ef6contrib.codeplex.com). Zorrilla fez várias contribuições para o pacote do Microsoft EF, como Pluralização Personalizada, AddRange, RemoveRange e AddFrom­Assembly—todos os recursos escritos em colunas ou artigos anteriores. Zorrilla tem várias ajudas adicionais que ele mantém no site ef6contrib.codeplex.com, incluindo:

  • Um serviço de Pluralização em espanhol pré-configurado (que foi incorporado no projeto do EntityFramework Reverse POCO Code First Generator discutido anteriormente).
  • Dois métodos mais convenientes para adicionar configurações do API do Fluent para um modelo Code First no tempo de execução.
  • Várias operações que você pode usar com migrações do Code First que não foram incluídas no EF, como DatabaseCollation, GrantTablePermission e RevokeTablePermission.
  • Um inicializador que funciona com migrações chamadas DropAndMigrateDatabaseToLatestVersion.
  • Um conjunto de tipos de analisador de consulta que nivela EF6 interceptores e resolvedores de dependência.

O que eu sempre adorei sobre as adições de Zorrilla para o EF é que ele pega o código escrito e usado repetidamente em seu próprio trabalho e encapsula para compartilhar com outros. Os analisadores, em particular, são muito legais. É possível configurar os parâmetros pelos quais você deseja medir o desempenho da execução do banco de dados EF e a qualidade do alinhamento do código com suas expectativas. Também há um analisador que verifica consultas não parametrizadas. Se você adicionar o interceptor para a classe DbConfiguration (outro recurso EF6), analisará todos os comandos de um determinado DbContext. O projeto CodePlex tem vários testes e amostras que permitem explorar os analisadores, assim como outras ferramentas incluídas no Entity Framework 6 Contrib. A Figura 3 mostra uma classe DbConfiguration das amostras que adiciona o PerformanceInterceptor e especifica se deve verificar três dos quadro analisadores na coleta.

Figura 3 Configurando alguns analisadores do Entity Framework 6 Contrib

public class Configuration : DbConfiguration  {
    public Configuration() {
      this.AddDependencyResolver(new CustomResolver());
      this.AddInterceptor(new PerformanceInterceptor((msg =>
      {
        Console.WriteLine(msg.Message);
      })));
    }
    private class CustomResolver : IDbDependencyResolver{
      public object GetService(Type type, object key) {
        return null;
      }
      public IEnumerable<object> GetServices(Type type, object key) {
        // You can use here your preferred IoC container
        if (typeof(IPerformanceAnalyzer).IsAssignableFrom(type)) {
          return new List<IPerformanceAnalyzer>(){
             new ExecutionTimePerformanceAnalyzer(TimeSpan.FromSeconds(3)),
             new UnparametrizedWhereClausesPerformanceAnalyzer(),
             new TopSlowQueriesPerformanceAnalyzer(10)
          };
        }
        return Enumerable.Empty<object>();
      }
    }
  }

Com base na configuração, a janela de console exibirá qualquer relatório dos analisadores.

Extensões EF e Várias Ferramentas

Estas são apenas algumas ferramentas que descobri ser realmente benéficas para o meu trabalho. Há outras que desejo garantir que você não ignora, mas não tenho espaço para falar sobre todas elas aqui. Erik Ejlskov Jensen tem uma lista de algumas das extensões mais notáveis nesta postagem do blog: “Entity Framework 6 (e SQL Server Compact) (5)–Extensões do Entity Framework 6” (bit.ly/SxxPc5). A lista inclui uma versão atualizada do EF Caching Provider, que permite um cache de segundo nível para EF6 (bit.ly/UePlmU); Trackable Entities, uma substituição para as Self-Tracking Entities interrompidas (trackable.codeplex.com); e alguns projetos adicionais que resolvem a funcionalidade de operações em massa. Ejlskov Jensen é um SQL Server CE MVP e além de contribuir com muitas ótimas funcionalidades relacionadas ao SQL CE diretamente para o EF6, ele tem uma extensão do Visual Studio muito popular, SQL Server Compact Toolbox, que inclui muitos recursos para ajudar com o EF. Se você usar o SQL CE com ou sem EF, a caixa de ferramentas é uma extensão fundamental. Por fim, eu desejo adicionar uma mensagem sobre o trabalho que Jimmy Bogard realizou em uma série de postagens do blog que ele chama de “Soluções alternativas do recurso de EF ausente”, incluindo um que aumenta o EF6 para fornecer filtros globais para um Modelo EF e está disponível como um pacote NuGet. É possível saber mais sobre isso na sua postagem do blog em bit.ly/1prZv0a.


Julie Lermané uma Microsoft MVP, mentora e consultor do .NET Framework que vive nas montanhas de Vermont. Você pode encontrá-la em apresentações sobre acesso de dados ou sobre outros tópicos .NET em grupos de usuários e conferências em todo o mundo. Seu blog está em thedatafarm.com/blog e é autora do livro “Programming Entity Framework” (2010), além das edições Code First (2011) e DbContext (2012), todos da O’Reilly Media. Siga Julie no Twitter em twitter.com/julielerman e confira seus cursos da Pluralsight em juliel.me/PS-Videos.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Mikael Eliasson, Simon Hughes e Unai Zorrilla