Entity Framework: Criando um CRUD com T4

Veja neste artigo como implementar uma Classe CRUD utilizando o T4 (Text Template Transformation ToolKit) e Entity Framework.

O T4 é uma ferramenta da Microsoft que pode ser utilizada para geração de código fonte. Neste post vamos mostrar o poder dessa ferramenta junto com o Entity Framework e o quanto você pode agilizar seu processo de desenvolvimento com ela.

Nota: Caso você não saiba muito bem como trabalhar com o Entity Framework, a DevMedia possui esses ótimos cursos sobre o tema:

Criaremos um CRUD básico utilizando o T4. Primeiro você precisa de uma base de dados SQL Server para que possamos implementar, ou faça o download da base que está disponível junto com o código fonte do artigo. Abra o Visual Studio e crie um novo projeto clicando em File -> New -> Project, conforme a Figura 1.

Figura 1. Criando um novo Projeto.

Na janela seguinte digite “empty” na caixa de pesquisa e selecione BlankSolution e altere a propriedade Name para FirstT4Entity ou para nome que preferir, conforme mostra a Figura 2.

Figura 2. Criando uma Blank Solution(Solução em Branco).

Se olharmos no Solution Explorer veremos que foi criada uma solução vazia, então agora clique com o botão direito do mouse e escolha Add... e em seguida New Project.

Crie um projeto do Tipo Console Application e altere a propriedade Name para FirstT4Entity, conforme demonstrado nas Figuras 3 e 4.

Figura 3. Adicionando um projeto na Solução

Figura 4. Adicionando um novo projeto

Agora vá até o Solution Explorer e clique com o botão direito do mouse sobre o projeto Console Application escolha Add... New item. Escolha a opção ADO.NET Entity Data Model e na propriedade Name coloque T4Entity. Veja as Figuras 5 e 6.

Figura 5. Adicionando um Novo Item

Figura 6. Adicionando um Novo Item

Agora você deve selecionar Generate from database e clicar em Next, conforme a Figura 7.

Figura 7. Selecionando Tipo de Data Model

Clique no botão New Connection e configure as informações conforme seu banco de dados, então clique em OK. No textBox coloque T4Entities e marque a opção “Yes, Include de Sensitive data in the connection string.” e clique em Next. Selecione as tabelas desejadas e clique em Finish, conforme os passos das Figuras 8 a 11.

Figura 8. Tela inicial da configuração do banco de dados.

Figura 9. Configurando o Acesso ao Banco

Figura 10. Nomeando seu Contexto

Figura 11. Selecionando as Tabelas.

Agora precisamos adicionar um arquivo T4(.tt) ao nosso projeto, porém não vamos utilizar a forma padrão que seria clicar sobre o projeto e add new item. Vamos adicionar pelo arquivo Edmx, assim algumas funções que precisaríamos implementar já virão prontos, nos poupando tempo. Com o seu Edmx aberto, clique com o botão direito do mouse e acesse a propriedade Add Code Generation Item. E escolha a opção ADO.NET EntityObject Generation e na propriedade Name coloque T4Entity.tt. Veja os passos nas Figuras 12 e 13.

Figura 12. Adicionando um Code Gerneration Item.

Figura 13. Selecionando o Tipo de Template

Quando é realizada dessa forma, a geração do arquivo T4(.tt) é feita pelo Visual Studio, gerando um script para gerar todas as classes do Entity. Porém não é o que queremos. É necessário gerar um CRUD, no entanto, fazendo dessa forma poupa um trabalho desnecessário, que é a de criar toda a Integração do .tt com o nosso Entity. Vamos precisar apagar uma parte do código contido no arquivo .tt. Para isso você deve apagar tudo que estiver entre “[assembly: EdmSchemaAttribute()]” e “<#+//////Declare Template Public Properties.”. Outro detalhe muito importante é que quando você adiciona o arquivo .tt dessa forma ele automaticamente para de gerar as classes do Entity automaticamente, pois ele passa a respeitar o código do arquivo. Por isso, abra o seu edmx e acesse a aba Properties, alterando a propriedade Code Generation Strategy para “Default”. Veja nas Figuras 14 e 15.

Figura 14. Arquivo Template(.tt)

Figura 15. Propriedade do Edmx.

Agora vamos implementar o código no T4 para que nossa classe CRUD seja gerada automaticamente.

Sempre que se trabalha com T4 é aconselhável criar suas classes como partial, assim, se precisar implementar alguma coisa a mais para uma classe específica, é só criar um outro arquivo com partial e não precisa mexer no T4.

Junto as using já existentes no T4 é necessário colocar a FirstT4Entity, System.Linq.Expressions e System.Linq, conforme a Listagem 1.

Listagem 1. Incluindo as Namespaces

using FirstT4Entity; using System.Linq.Expressions; using System.Linq;

Depois de já inseridas as namespaces necessárias para o funcionamento da nossa classe, devemos criar a namespace da nossa classe, conforme a Listagem 2. Nesse caso foi colocado o nome de DAO, mas pode ser colocado a namespace desejada.

Listagem 2. Criando a Namespace

namespace DAO { }

Agora vamos implementar o código que irá gerar as classes e as funções Add,Update, Delete, Find e duas assinaturas para o método GetAll do nosso CRUD. Para entendermos melhor vamos fazer isso por parte. Inicialmente é necessário criar um looping para criarmos todas as classes de acordo com nossas entidades. Veja na Listagem 3.

Listagem 3. Inserindo nome da Classe

<# foreach (EntityType entity in GetSourceSchemaTypes<EntityType>() .OrderBy(e=>e.Name)) { #> <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#>DAO { } <# } #>

Após a declaração da namespace estamos realizando um foreach de todas as entidades do nosso contexto para gerar a classe DAO de cada um.

Repare que sempre que precisamos codificar, é necessário que o código esteja entre os sinas “<#” e “#>”, que é para indicar onde começa e onde termina. O que fica fora destes sinais é apenas texto escrito e será transportado para o arquivo .cs exatamente como está no arquivo .tt.

Logo abaixo realizamos outro foreach para localizar nosso contexto e criar uma instância dele para podemos incluir, alterar e excluir nossas entidades. Veja na Listagem 4.

Listagem 4. Criando o Contexto

<# foreach (EntityContainer container in GetSourceSchemaTypes <EntityContainer>()) { #> <#=code.Escape(container)#> _entities= new <#=code.Escape(container)#>(); <# } #>

Agora vamos implementar os métodos Add, Update, Delete, conforme a Listagem 5.

Listagem 5. Implementando os Métodos

public void Add(<#=code.Escape(entity)#> _ent) { _entities.AddTo<#=code.Escape(entity)#>(_ent); _entities.SaveChanges(); } public void Update(<#=code.Escape(entity)#> _ent) { _entities.ApplyCurrentValues("<#=code.Escape (entity)#>", _ent); _entities.SaveChanges(); } public void Delete(<#=code.Escape(entity)#> _ent) { _entities.DeleteObject(_ent); }

Os três métodos acima são bem simples e bem parecidos. O próximo método a ser implementado é o método Find que exigem um pouco mais de programação. Para implementá-lo é necessário outro foreach para que ele encontre a chave da entidade para utilizarmos como filtro, conforme segue o código da Listagem 6.

Listagem 6. Implementando o Find

<# foreach (EdmProperty property in entity.Properties.Where (p => p.DeclaringType == entity && p.TypeUsage.EdmType is PrimitiveType)) { if(ef.IsKey(property)) { #> public <#=code.Escape(entity)#> Find(<#=code.Escape(property.TypeUsage)#> _<#=code.Escape(property)#>) { <#=code.Escape(entity)#> _ent = new <#=code.Escape(entity)#>(); _ent = _entities.<#=code.Escape(entity) #>.Where(e => e.<#=code.Escape (property)#> == _<#=code.Escape(property) #>).FirstOrDefault(); return _ent; } <# } }#>

Repare que logo abaixo do foreach utilizamos também um if, que serve para checar se a propriedade em questão é a chave da entidade. Caso seja, ele utiliza essa propriedade como filtro para nosso método Find.

Como último passo para criação do CRUD precisamos implementar duas assinaturas GetAll: uma delas não possuirá parâmetro e a outra receberá uma expressão lambda como parâmetro. Dessa forma, uma assinatura irá retornar um IQueryable contendo todos os registros da sua entidade e a outra retornará um IQueryable levando em consideração a expressão lambda passada como parâmetro. Na Listagem 7 você vê a implementação dos métodos GetAll.

Listagem 7. Implementando os GetAlls

public IQueryable<<#=code.Escape(entity)#>> GetAll() { return _entities.<#=code.Escape(entity)#>.Select(e=>e); } public IQueryable<<#=code.Escape(entity)#> > GetWithFilter(Expression< Func<<#=code.Escape(entity) #>,bool>> where) { return _entities.<#=code.Escape(entity)#>.Where(where); }

Agora salve o arquivo .tt e vamos acessar o arquivo T4Entity.cs. Para isso, acesse o solution explorer e expanda o arquivo .tt: dê um duplo clique no arquivo.cs. Lá estará todas as classes referentes a cada entidade com os seus métodos. As Figuras 16 e 17 exibem como seu código deve ficar.

Figura 16. Classe CategoryDAO

Figura 17. Classes DAO como Seus Métodos.

No começo parece meio complexo, mas depois será visível como pode ser útil e ágil a implementação de classes com T4. Além disso, essa classe é reaproveitável para qualquer conexão com o Entity.

Espero que tenham gostado deste artigo e que tenha sido útil a vocês.

Até a próxima!

Artigos relacionados