Objetivos
Esta série de artigos visa mostrar com detalhes um exemplo relativamente complexo de aplicação do Entity Framework em projetos do nosso dia-a-dia. Com isso, queremos demonstrar de forma imparcial os ganhos que obtivemos com a aplicação desta nova forma de trabalhar com dados que se revela muito promissora.
Esta série de artigos aplica-se aos desenvolvedores que usam .NET Framework 2.0 e gostariam de aprender ou convencer seus pares a adotar o .NET Framework 3.5. Estes exemplos são criados utilizando o Visual Studio 2008, banco de dados SQL Server 2005 e também, ferramentas auxiliares com o NUnit (sem custo) e ReSharper (possui custo – mas é opcional). Além disso, é necessário obter o Service Pack 1 do .NET Framework 3.5.
Introdução: Acesso a Dados
O acesso a dados é uma das tarefas mais corriqueiras de um desenvolvedor de aplicações empresariais comuns, como cadastros web por exemplo. Se você estiver utilizando a plataforma .NET, provavelmente cansou de escrever camadas de acesso a dados repetitivas para depois sofrer com mudanças no esquema, mudanças nas colunas, novos joins, erros de sintaxe e erros e compilação de comandos SQL.
Provavelmente você também já deve ter ouvido falar de várias ferramentas que tendem a ajudar na tarefa de mapear tabelas de bancos de dados relacionais em objetos autênticos no .NET. E provavelmente você acabou experimentando e usando com sucesso o NHibernate em sua mais recente versão, conseguindo acelerar radicalmente o tempo de criação da sua camada de acesso a dados. Entretanto, também sofreu com a criação dos trabalhosos arquivos de mapeamento do NHibernate. Com o tempo relativamente curto, nós, desenvolvedores, geralmente evitamos lidar com tecnologias completamente novas sem antes testar várias situações problemáticas. Sem o uso de NHibernate e sem o uso de ADO.NET clássico, evita-se a busca dos inúmeros outros fornecedores de soluções similares haja vista que cada tipo de ferramenta, paga ou não, necessita de um tempo de adaptação, power-users, treinamento de equipe e incorre em custos para o cliente ou projeto final, que custeia a curva de aprendizado do time.
Com o surgimento do framework 3.5, o mundo .NET sofreu uma revolução, não apenas uma evolução: foi introduzido o LINQ, que basicamente uniformiza o acesso a qualquer tipo de dados da atualidade. Neste release foi lançado também o Linq to SQL, que passou a ser um produto para simplificar radicalmente a acesso a dados para o SQL Server 2005. Muitas pessoas utilizaram e ainda utilizam o Linq to SQL. Entretanto, o LINQ to SQL não é considerado pela comunidade como uma solução corporativa pois é muito mais focado em acelerar o desenvolvimento de cadastros simples e também, só funciona com o SQL Server. Para exemplos de LINQ sugiro visitar estes links: Introdução ao LINQ, Página do LINQ do MSDN e Primeiros Exemplos com LINQ .
O lançamento do Service Pack 1 do .NET introduziu o Entity Framework, que passou a ser a principal ferramenta de mapeamento objeto-relacional disponível para a comunidade .NET. É considerada uma solução corporativa e está no mainstream do desenvolvimento da Microsoft. Com os exemplos buscaremos mostrar como foi a adoção desta ferramenta, suas vantagens e desvantagens. Com esta ferramenta, já é possível ignorar a necessidade o NHibernate, mesmo que este framework seja muito mais maduro que o seu concorrente. Isso se faz verdade pois com isso conseguimos diminuir o número de dependências externas. Outra vantagem é que não se cria a dependência de ferramentas não-Microsoft, argumento que é válido em muitas organizações que visam diminuir os supostos riscos de uma ferramenta open-source.
Preparação do Exemplo: Gerenciamento de Faculdade
Para começar a explicar como funciona o Entity Framework, vamos apresentar nosso exemplo. Este exemplo poderá ser a base de muitos outras postagens e portanto é bom que se entenda com calma quais são as especificações do sistema.
O sistema em questão é um sistema relativamente simples de controle de alunos, turmas e professores de uma faculdade. Os requerimentos sistema estão listados nos itens abaixo, de forma muito simplificada inicialmente:
1. O sistema suportará várias unidades (filiais) da faculdade.
2. A faculdade possui um grupo de disciplinas comum a todas as unidades.
3. Cada unidade possui uma turma distinta de uma dada disciplina. Isso permite que a mesma disciplina seja oferecida em diferentes unidades.
4. Cada unidade contém seus respectivos alunos. Os alunos não poderão utilizar mais do que uma unidade.
5. Cada aluno deverá conter um cadastro básico obrigatório e um cadastro não-básico opcional.
- Cadastro básico: Nome, Formas de Contato
- Cadastro não básico: Campos livres, decididos de acordo com cada unidade. Por exemplo, deverá ser possível montar um questionário sócio-econômico.
6. Cada professor pode ter uma ou mais turmas.
7. O sistema deverá suportará o cadastro de turmas. Cada turma é única em todo o sistema, independente de qual unidade ela pertença
- O sistema deverá suportar o envio de mensagens para os alunos da turma
- Deverá ser possível guardar informações do aluno em cada turma que estiver matriculado
8. Cada professor pode ministrar aulas em mais de uma unidade. Para os administradores de cada unidade, é necessário saber quem são os seus professores pois assim conseguem determinar os custos de estacionamento e honorários. A relação de professor x unidade existe independentemente de haver turmas para o professor.
Agora vamos citar alguns outros requisitos de negócio necessários para prosseguir com o exemplo:
1. O sistema deverá rodar em plataforma Web
2. O sistema poderá expor seus dados utilizando o padrão REST para Web Services.
Preparação do Exemplo: Modelagem dos dados
Considerando os requerimentos listados e levando em conta a necessidade de simplicidade do exemplo, vamos demonstrar a criação do modelo de dados através do uso de uma ferramenta que gera diagramas ORM. O ORM é uma ferramenta de engenharia de software conhecida no mercado que gera diagramas demonstrando a relação entre as entidades e complementa a notação UML ao especificar sistemas. Clique aqui para saber sobre ORM.
A ferramenta utilizada para gerar se chama Natural ORM Architect. Ela é Open Source e é exposta como um plugin do Visual Studio 2008. Trata-se de uma ferramenta completa e bem elaborada – quem dera se houvesse uma ferramenta similar totalmente open source para usar com UML! Clique aqui para obter esta ferramenta.
Para modelar um sistema geralmente a documentação é lida com os seguintes focos: buscar as entidades e buscar as relações/ações entre tais entidades. Tomando essas ações e aproveitando que temos um exemplo corriqueiro à disposição, consegue-se chegar no seguinte diagrama ORM:

Diagrama ORM representando as entidades deste exemplo - clique pra aumentar todas as imagens deste artigo
Ao observar este diagrama devemos que lembrar:
1. Os retângulos são entidades formais – nossos “objetos” do domínio – de quem falamos. No caso, Unidade, Professor, Aluno e Turma.
2. Os fatos são as ligações entre as unidades. São os “verbos” de estado ou ação, que determinam como uma entidade se relaciona com outra. Estas relações podem ser de alguns tipos bem conhecidos: 1-1, 1-N, N-1. No nosso exemplo, a Unidade tem relação 1-N com Aluno, Aluno possui uma relação N-N com Turma, e assim vai.
3. O fato também pode ser “objetificado”. Isto é, a relação de alunos com turmas, apenas de ser N-N, é qualificada, isto é, a relação possui propriedades úteis. Isso ficará mais claro durante a criação do banco de dados. Quando um fato é objetificado, ele recebe um círculo no diagrama.
4. O “risco” roxo acima de cada fato significa a multiplicidade. O lado da relação que tiver o risco possui multiplicidade N.
5. A “bolinha” ao lado de cada relação indica que a presença da entidade na relação é obrigatória. Um exemplo de leitura neste caso seria: “Um Professor ministra em pelo menos uma ou mais Unidades. No caso inverso, Turma pode conter 0 ou mais alunos. Também, podemos ver que a Turma pode existir sem alunos.
6. Os termos colocados acima de cada relação demonstram como é efetivamente a relação de cada entidade. Isto é feito para facilitar a leitura do diagrama.
7. É possível estender o modelo acrescentando propriedades às entidades, como por exemplo, uma suposta classe “Endereço” à entidade Aluno.
É possível complicar muito mais este tipo de diagrama, pois é possível definir “constraints” no modelo, igualdades, “and”, “or” e vários outros tipos de condições entre as entidades. Embora Turma permita alunos de unidades diferentes, essa restrição é mais fácil de ser feita no software do que no banco de dados – não pode haver mistura de alunos de unidades diferentes.
Preparação do Exemplo: Criação do banco de dados
Muitas correntes de pensamento do mercado assumem que é interessante partir do modelo de dados final para depois criar o banco da dados – o objetivo disso é que não se crie uma aplicação já dependendo de um esquema pré-desenhado e muitas vezes, não tão bem pensando como poderia ser.
No nosso caso, temos um modelo misto. Vamos usar a modelagem acima para criar o banco e dados para depois, referenciar este esquema recém-criado no Entity Framework, pois este costuma ser o jeito mais prático de montar o modelo da aplicação.
Como a criação de tabelas é uma atividade corriqueira, vamos acelerar este processo e vamos montar as relações de forma que por enquanto, não haja nenhum tipo de ação ao alterar/remover linhas de um relacionamento entre tabelas, isto é, sem UPDATE ou DELETE action.

Esquema do banco de dados
O modelo acima está um pouco simplificado em termos de número de campos por tabela. Com particularidades no design temos as seguintes observações:
1. Nas entidades Unidade, Professor, Aluno e AlunoNasTurmas foi criada a coluna [Detalhes]. Esta coluna é do tipo XML. Este é um tema que será detalhado mais para frente, mas já se pode adiantar que o uso deste tipo de coluna proporciona o uso de documentos XML neste tipo de coluna, com total suporte busca e manipulação de informação. No .NET, este tipo de dados é representando como String simples.
2. Foi acrescentado ao modelo a entidade DisciplinaOferecimento, que contém os tipos de semestre que são oferecidas as disciplinas. Ela indicará que uma disciplina é semestral, anual ou de férias, por exemplo.
3. A entidade Disciplina usa como chave o seu próprio código, que contém letras e números.
4. A relação entre Turma e Aluno é uma relação N-N qualificada. Ela contém várias propriedades interessantes e também possui um campo do tipo xml para armazenar outras informações não previstas neste momento, como por exemplo, a nota de cada prova.
O script completo da criação do banco e a solução do Visual Studio se encontram nos anexos listados no final deste artigo.
Preparação do Exemplo: Criação do modelo de dados com Entity Framework
Com o banco de dados construído, já temos condições de criar um modelo de dados consistente para nosso exemplo para uso no .NET. Para prosseguir com esse exemplo é necessário possuir o .NET Framework 3.5 SP1 instalado.
A princípio nossa solução será criada com um projeto contendo o modelo de dados e outro projeto contendo os testes unitários para podemos testar o modelo. Para facilitar a compreensão do processo siga os próximos passos:
1. Crie uma solução com um projeto Class Library. Crie uma pasta chamada BusinessEntities ou similar. Esta pasta irá conter o modelo de dados e todas as classes complementares ao modelo. Optamos pelo nome óbvio de GerFac para que o nome do projeto e de suas referências fique sucinto. Note que também eu já tenho no projeto o modelo ORM deste sistema, pois como foi dito antes, a ferramenta Natural ORM permite que se use o Visual Studio 2008 para desenhar os diagramas – os arquivos .orm são considerados como “Solution Items”.
2. Clique com o botão direito na pasta BusinessEntities e adicione um novo item do tipo “ADO.NET Entity Data Model”. Na tela subseqüente escolha “Generate from database”.

Criando uma nova solução.
3. Conecte-se à base de dados contendo as tabelas do exemplo. Ao realizar a conexão bem sucedida, salve a conexão com o nome sugerido no App.Config.

Armazenando os dados da connection string no arquivo de configuração
4. Escolhas as tabelas criadas conforme o exemplo abaixo. Aceite o namespace padrão do modelo. Clique em Finish.

Escolhendo as tabelas do banco da dados
5. Se tudo correu bem, você conseguirá visualizar seu modelo de dados como mostra a figura abaixo. Também será possível ver as barras de ferramentas do Entity Framework. Analise o modelo. Note que algumas tabelas parecem ter sumido. Quando há uma relação N-N, a tabela de junção não é mostrada no modelo. Na prática, na relação de Unidade e Professor, a classe Unidade possui uma lista de [Professor] e a classe Professor possui uma lista de [Unidade].

Modelo de dados representado como classes em .NET
6. Salve e compile seu trabalho. Corrija eventuais erros. Analise o arquivo .designer do modelo. Esse arquivo .designer possui a representação de cada classe do modelo, assim como suas propriedades e métodos. Note também que esse arquivo sempre é gerado automaticamente – nunca mexa com ele diretamente.
7. O objetivo é tornar fácil o acesso à string de conexão do modelo de dados. A classe ConfigurationManager do .NET 2.0 facilita este processo. Vamos criar uma classe estática contendo um método estático que realize esta tarefa para nós. Para isso, crie uma pasta chamada Config e dentro desta pasta, crie uma classe chamada AppConfiguration. Adicione ao projeto uma referência ao assembly System.Configuration. Adicione o código abaixo à classe AppConfiguration:
using System.Configuration;
namespace Accendis.Artigos.GerFac.DataModel.Config
{
public static class AppConfiguration
{
#region Public Properties
/// Returns the connectionstring for the application.
public static string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["GerFacEntities"].ConnectionString;
}
}
#endregion
}
}
8. Compile seu projeto e corrija eventuais erros. Ao final da tarefa sua solução deverá ficar como a figura abaixo:

Detalhe do projeto contendo o modelo de dados (referências e organização das pastas)
Preparação do Exemplo: Primeiros Testes
Vamos começar a brincar com o nosso modelo de dados para verificar que o mesmo funciona. Para isso, adicione mais um projeto do tipo Class Library à solução. Denomine o projeto como UnitTests.

Referências do projeto de teste - observe a referência ao NUnit!
Para poder executar os teste unitários, é necessário instalar o NUnit em sua versão mais recente. O NUnit é um framework para execução e automação de testes unitários open source e livre. É de longe a ferramenta de testes mais utilizada no mercado, embora exista ferramentas mais modernas e completas como por exemplo, o pacote de testes do Visual Studio Team System. O NUnit pode ser obtido a partir deste link.
Adicione uma referência ao projeto contendo o modelo de dados conforme a figura acima. Crie também uma classe chamada UnidadeTest, que será o lugar da primeira experiência prática com o Entity Framework. Copie o arquivo App.config do projeto DataModel para o projeto de testes. Isso é necessário para que o ConfigurationManager (criado por você anteriormente) que está no projeto DataModel consiga enxergar a connection string. Na prática, o projeto que chama o assembly DataModel injeta a string de conexão. Seja ele projeto de testes, Console Application, Windows ou Web. E essa injeção é possível com o uso do ConfigurationManager.
Uma ferramenta paga muito interessante para se trabalhar é o ReSharper. Ele é ótimo para verificar erros de codificação antes de compilar os dados mas uma das minhas funcionalidades favoritas é a execução de testes unitários. Esta ferramenta acelera muito a execução dos testes e permite ainda, que o teste escreva numa espécie de console. O ReSharper pode ser obtido a partir deste link. Vale a pena conferir!
Para terminar nosso teste básico, vamos listar e modificar entidades do tipo Unidade. Para isso faça o seguinte:
1. Crie um backup do banco completamente vazio.
2. Edite a tabela Unidade diretamente no SQL Server. Crie 3 unidades. Com isso teremos dados para retornar. Não se preocupe com o campo [Detalhes] neste momento.

Criando unidades para o teste
3. Adicione referência ao assembly System.Data.Entity ao projeto. Se estiver o utilizando o ReSharper, ele tentará fazer isso por você utilizando um aviso de erro.
4. Vamos criar um primeiro teste que indica que somos capazes de buscar as unidades do banco de dados e mostrar na tela. Para alcançar esse objetivo adicione o seguinte código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Accendis.Artigos.GerFac.DataModel.BusinessEntities;
using Accendis.Artigos.GerFac.DataModel.Config;
using NUnit.Framework;
namespace Accendis.Artigos.GerFac.UnitTests
{
[TestFixture]
public class UnidadeTest
{
[Test]
public void ListarUnidades()
{
//Abrir uma conexão ao data model e implicitamente, abrir uma conexão com banco de dados
//utilizando o Entity Framework. Utilizar o bloco using para que os recursos sejam
//liberados ao sair do bloco using.
using (GerFacEntities entities = new GerFacEntities(AppConfiguration.ConnectionString))
{
//obter as entidades do banco de dados, materializar numa lista e realizar
//as operações desejadas com a lista.
List unidades = (from u in entities.Unidade select u).ToList();
foreach (Unidade unidade in unidades)
{
Console.WriteLine(string.Format("{0} - {1}",
unidade.Nome, unidade.Descricao));
}
Assert.IsTrue(unidades.Count() > 0);
}
}
}
}
5. Execute este teste. Se estiver com o ReSharper, haverá uma bolinha para clicar no lado de cada teste, como é mostrado na figura abaixo. Escolha a opção “Run”. Veja o resultado do teste na janela “Unit Test Sessions”.

Menu do Resharper para chamar a execução do teste unitário.

Resharper: Unit Test Explorer indicando o resultado da execução do teste unitário
É isso aí! Se você conseguiu chegar até aqui parabéns! Com isso você já está utilizando o Entity Framework e tem acesso total ao modelo de dados. Nós te encorajamos a brincar com as entidades e suas relações. Note que por exemplo, a entidade Unidade possui várias propriedades do tipo EntityCollection, que na prática representa a sua lista de professores ou então, a sua lista de seus alunos.
Cabe ainda alguns comentários sobre este primeiro teste:
1. A grande vantagem de usar o Entity Framework é o uso do LINQ para realizar consultas. Com isso, eu consigo fazer consultas tanto a objetos como dados que estão no banco de dados.
2. Só é possível enumerar 1 vez os dados quando eles são trazidos do banco de dados. Para isso, é muito útil colocar o que é recebido numa lista genérica. Por isso é utilizando o método ToList().
3. O LINQ acrescenta vários métodos úteis a objetos comun do .NET como coleções genéricas e enumerações (tudo o que suporta o foreach). Com isso, é possível transformar enumerações em listas, dicionários, encontrar máximos, somas e muito mais. Vamos falar sobre isso nos próximos posts.
Aguarde os próximos posts desta série!
Atenciosamente,
Equipe Accendis – www.accendis.com.br
Clique aqui para baixar os anexos deste artigo.
.NET, asp