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.
- <#=Accessibility.ForType(entity)#>: esse trecho vai preencher o tipo de acesso da Entidade, ou seja, private, public, sealed, etc;
- <#=code.SpaceAfter(code.AbstractOption(entity))#>: aqui é preenchido se a entidade for abstract;
- <#=code.Escape(entity)#>: esse comando traz o nome da entidade.
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
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo