Entity Framework: Code-First, Database-Never

Conheço desenvolvedores que gostam do Entity Framework (EF), mas nunca vi um DBA que fale bem dele.

Para explicar parte desse fenômeno, quero dar um exemplo baseado no projeto do ARDA (https://github.com/dxbrazil/arda).

[UPDATE 12/07]  Obrigado ao André Baltieri por gravar um vídeo com uma explicação tão didática. Depois de assistir ao vídeo, já estou entrando em contato para adquirir o curso sobre Entity Framework. Quem sabe agora posso escrever um EF decentemente. Cuidado que o vídeo tem SPOILER.

https://www.youtube.com/watch?v=EmSIlaPKzGM

Code-First

Ao usar o code-first, as tabelas são geradas automaticamente a partir das classes modelos escritas em C#. Isso permite que o desenvolvedor fique focado dentro do Visual Studio sem precisar abrir o SQL Management Studio para acessar o banco de dados. Na verdade, não é preciso escrever uma linha de script T-SQL.

Durante o desenvolvimento, usamos o Entity Framework Core (EF Core) e adotamos o code-first para modelar nosso banco de dados.

Eu juro que a ideia não foi minha – embora o histórico do Git diga o oposto!

[fcatae committed on Apr 26, 2016] Configure the database using EF migrations
https://github.com/DXBrazil/Arda_old/commit/b00a4f2943973e2ddb2a734e1e5b3640503ae05a

A ideia de code-first é interessante em um caso primeiro momento. Por exemplo, é ótimo para escrever tutoriais:

[Entity Framework Core] ASP.NET Core - New database with Visual Studio 2017
https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db

[Entity Framework Core] Getting Started on .NET Core
https://docs.microsoft.com/en-us/ef/core/get-started/netcore/

Ao meu ver, as vantagens acabam por aí.

Database-Never

O problema em adotar uma estratégia de code-first é que o desenvolvedor não valida o conteúdo gerado no banco de dados.

Por exemplo, no ARDA temos uma tabela principal chamada WorkloadBacklogs. Os itens registrados no sistema podem ser classificados como Workload ou Backlog.

image

Do ponto de vista de modelagem de dados, a nomenclatura é estranha.

  • Por que todas as colunas começam com “WB”? WBID, WBActivityActivityID, WBCreatedDate, WBDescription, etc…
  • Por que a coluna “WBActivityActivityID” não poderia ser chamada apenas de “ActivityID”?
  • Por que a coluna “WBCreatedDate” armazena datas com precisão de microssegundos? 2017-01-31 20:55:02.5101859

Outro exemplo é a tabela WorkloadBacklogTechnologies, que já tem um nome curioso.

image

As colunas possuem os nomes de WBUTechnologyID, TechnologyTechnologyID e WorkloadBacklogWBID.

E o que seriam esses campos de UniqueIdentifier?

UniqueIdentifier

O tipo de dados UniqueIdentifier (também conhecidos como GUID) é um valor de 16-bytes representado no formato:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Os identificadores GUID foram muito usados em componentes COM/COM+ devido à garantia de que eles são únicos mesmo em ambientes descentralizados. Entretanto, é muito estranho analisar uma tabela com esses campos, pois os dados parecem criptografados:

image

Em um banco de dados, os campos UniqueIdentifier são desencorajados:

  • Tipo de dados INTEGER é mais compacto e ocupa apenas 32-bits
  • Campos UniqueIdentifier são aleatórios e causam fragmentação de tabela

Resumindo: DBA’s preferem campos INTEGER com IDENTITY.

NVARCHAR(max)

Existem dois tipos de NVARCHAR: limitado e ilimitado.

Em geral, as tabelas devem usar campos NVARCHAR especificando o tamanho máximo em caracteres. Isso permite que o banco de dados mantenha todos os dados dentro do mesmo bloco físico (8kb) do disco.

Porém, observamos exatamente o oposto na definição da tabela.

image

Se você usa o Entity Framework com code-first, é muito provável que os campos string estejam mapeados como NVARCHAR(max). Esse tipo de dado aumenta a fragmentação da tabela sem necessidade.

Próximo Artigo

As esquisitisses do Entity Framework não acabam por aqui. No próximo post, pretendo me aprofundar um pouco mais nos problemas que tivemos ao longo do projeto.

UPDATE: Gostaria de agradecer a todos que deixaram criticas ao artigo, pois todo comentário adiciona contexto ao texto original. O objetivo é mostrar motivos pelos quais "DBAs odeiam o EF", mesmo sabendo que a culpa é do desenvolvedor ao invés do framework. Esse é um exemplo real que aconteceu dentro da nossa própria casa (https://www.github.com/dxbrazil/arda). Posso certificar que esse descuido não foi exclusivo nosso, mas que acontece em vários outros lugares. Não deixem de acompanhar os próximos artigos e deixar seus comentários!