Introdução

Com o recém-lançado Visual Studio 2010, o C# passou por diversas melhorias. E para quem trabalha com automação do Excel utilizando VSTO (Visual Studio Tools for Office), a situação melhorou muito para o desenvolvedor C#. Até a versão anterior simplesmente não compensava o esforço de se fazer add-ins para Office utilizando C#. Por ser uma linguagem fortemente tipada e com tipagem estática, ao acessar os objetos COM do modelo de objetos do Office, era necessário realizar múltiplos casts para objetos em .NET existentes nos PIAs (Primary Interop Assemblies). Os PIAs, contêm o modelo de objetos de cada aplicação Office (Excel, Word, etc…) representados por “cópias” em .net de objetos COM. Para trabalhar com o modelo de programação do COM o VB.NET sempre foi melhor, permitindo parâmetros opcionais, variants e etc…, coisas até então inexistentes em C#.

O C# 4.0 agora suporta o sistema de tipagem conhecido por “tipagem dinâmica”. A tipagem dinâmica permite que o você chame métodos e propriedades que serão apenas resolvidos em tempo de execução, similar ao que acontece em Javascript. Essa resolução em tempo de execução é mais arriscada, mas, quando você bem o modelo de objetos, permite um código muito limpo, com quase nenhum cast desnecessário.

Na prática, com o C# 4.0, temos o mesmo poder de criar customizações para o Office utilizando a plataforma .NET que o VB.NET já oferecia. Com grande simplicidade, podemos criar aplicações muito legais e mais baratas, afinal, é possível usar todas as vantagens do Excel para manipular meus dados, sem a chatice de criar páginas em Web só para isso…

Nosso Exemplo

Este exemplo tentará ser um pouco mais completo. Vamos utilizar várias tecnologias para conseguir atingir nossos objetivos. Como ferramentas, utilizamos o VS2010 final, o Excel 2010 e o SQL Server 2008. Vamos realizar os seguintes passos:

1) Instalar os bancos de dados de exemplo do SQL Server 2008

2) Utilizar o Entity Framework para mapear os dados para a minha aplicação

3) Criar o serviço WCF que retorna a lista de produtos

4)Realizar testes simples do modelo e serviço

5) Adicionar a referência do serviço WCF ao Excel

6) Trazer os dados para o Excel

7) Trabalhar com os dados utilizando o C# e VSTO

Vamos detalhar cada passo com imagens, resolução de dúvidas mais recorrentes e vamos explicar tudo passo a passo. Vamos pra cima então!

Instalando o AdventureWorks para o SQL Server 2008

Atualmente os bancos de exemplo estão no CodePlex. O link para baixar os bancos de exemplo é: http://msftdbprodsamples.codeplex.com/releases/view/37109. Vale notar que para o exemplo temos instalado o SQL Server 2008 e não o R2, que saiu recentemente. Os bancos de exemplo são criados para cada versão do SQL Server e é importante instalar a versão adequada. Para esse teste, funciona qualquer versão do SQL Server.

Ao instalar, a dica é liberar antes o FILESTREAM para a instância do SQL Server 2008. Se não fizer isso antes, o instalador não coloca todas as versões do AdventureWorks. O instalador é bem inteligente e já faz a instalação de todas as versões do AW. Entre elas, tem uma versão Light, que é a que utilizamos no exemplo deste post.

Criando o modelo de dados com o Entity Framework

O EF nesta versão do .NET está com mais funcionalidades, entre elas, a possibilidade de criar modelo de dados em .NET e depois criar o banco de dados. Mas como já temos o banco de dados pronto, vamos criar um modelo de dados da forma mais simples possível, utilizando as opções padrão.

Antes de começar, criamos um projeto do tipo Class Library contendo uma pasta chamada BusinessEntities. Adicionamos a esta pasta um modelo de dados do EF:

image

Criamos uma conexão com o banco de dados AdventureWorksLT2008.

image

Utilizamos estas tabelas do modelo:

image

O modelo de dados ficou desta maneira:

image

Até aqui nada demais. Estamos usando o EF para automatizar o acesso a dados, sem grandes mistérios.

Criando o Serviço WCF que retorna a lista de produtos

Para este caso vamos hospedar o serviço no próprio IIS, utilizando as opções padrão do WCF. No caso vamos apenas renomear o serviço e as classes/interfaces para facilitar o uso deste serviço pelos clientes.

Após renomear os serviços, a solução ficou próxima disso:

image

O nome do serviço é ProductService e o método que traz todos os produtos se chama “GetAllProducts”. Veja o detalhe do código abaixo:

image

O método retorna uma lista de produtos que é trazida da biblioteca onde está guardado o modelo de dados do EF. Neste caso, abrimos o contexto que contém as entidades, obtemos os dados com o select e com o ForEach das listas genéricas, presente desde o .NET 2.0, utilizamos uma lambda expression que solicita que cada item da lista seja “desatachado” do contexto de dados do EF. Com isso, eu consigo passar a lista de produtos para os clientes remotos. Se eu não fizer o Detach, acontecerão vários erros ao trabalhar com os itens da lista de produtos, como por exemplo, tentativas de se conectar ao store de dados diretamente do cliente.

Vale lembrar que a string de conexão ao model deve ser declarada no arquivo de configuração do serviço. O construtor do AdventureWorkdLT20008Entities, objeto de contexto do EF responsável por controlar as operações com as entidades, sempre olha o arquivo de configuração para realizar a abertura da conexão. A imagem abaixo mostra o web.config com a informação de string de conexão ao modelo de dados do EF.

image

E finalmente, o serviço funcionando de forma padrão fica assim:

image

Na prática este é o jeito mais simples possível de se criar um serviço WCF. Não temos muitos segredos até o momento…

Testando o modelo de dados e o serviço WCF

Embora opcional, este passo consideramos muito importante para o desenvolvimento de qualquer coisa, desde um simples exemplo a uma complexa aplicação. Vamos realizar testes unitários muito simples capazes de indicar que o sistema está pronto para ser chamado do Excel. Não será preciso apelar para TDD neste caso pois nossos métodos são extremamente simples de serem testados. E não vamos contar com falhas como eventuais quedas do banco e do serviço, pois afinal, estamos querendo trabalhar mesmo é o com o Excel neste artigo. Vamos usar a estratégia de testes conceituais para este exemplo.

Crie um projeto usando o template de testes do VS2010. Adicione referência ao projeto contendo o DataModel. Adicione também uma referência ao serviço criado no passo anterior. As imagens mostram como referenciar o serviço ao projeto de testes. Basicamente o VS2010 identifica nos projetos da solução onde há um serviço WCF existente e puxa suas informações públicas, mostrando-as para nós.

image

image

Na guia “Advanced”, costumamos utilizar o List ao invés do Array para trabalhar com conjuntos de entidades por ser muito mais prático. Mas isso é opcional. Nós renomeamos a referência para ProductServiceReference para ficar mais legível no código final, pois este namespace que guardará o proxy do serviço WCF.

Com isso, vamos para o teste do modelo de dados:

image

Neste primeiro testes, conseguimos provar que o modelo funciona. E para comprovar, inicialmente coloquei um trace para que o teste escreva na janela de output o código e o nome de cada produto existente no banco. E o teste também contém um asserção para provar que há dados no banco para os testes. O teste executou ok. Fizemos o mesmo para o método que testa se o serviço realmente retorna dados.

image

Este teste realmente demorou mais para passar. Tínhamos nos esquecido de desatachar os objetos do contexto e por isso os dados nunca vinham. Outro erro que acontecia era o tamanho do conjunto de dados. O arquivo de configuração vem por padrão com um tamanho reduzido de bytes de tamanho da resposta. Tivemos que aumentar o tamanho do pacote no app.config do projeto de testes.

Vale lembrar que é recomendável sempre fechar o proxy do serviço WCF. Com o fechamento, o WCF libera os recursos como threads e alocações de memória que ele prepara para cada conexão ativa no serviço. E quando estamos trabalhando com o conceito de sessões no WCF, o fechamento indica o término de uma sessão. Abaixo mostramos o resultado final da tela de testes que o Visual Studio mostra quando os testes passam:

image

Como sempre, podemos debugar o teste, e no debug, podemos passar do cliente para o servidor na mesma execução. Com o F10, posso andar em cada método que é executado, e, se o cliente chama o servidor, o debug vai para o servidor e continua a execução, permitindo que tenhamos pleno controle da situação. Colocando o breakpoint tanto no servidor como no cliente, você sempre terá a informação de quem chamou quem e o que aconteceu durante as chamadas.

Criando uma customização de uma planilha do Excel 2010 com o VS2010

É possível customizar tanto documentos como a própria aplicação. Neste exemplo não é necessário criar uma customização do Excel, apenas é preciso adicionar novas funcionalidades a apenas uma planilha. Com isso, vamos optar pelo template de projeto Excel 2010 Workbook:

image

Ao prosseguir, teremos um projeto e um documento criado. Teremos algumas classes em .NET representando cada planilha do documento:

image

Como podemos ver, na prática um projeto com VSTO é muito similar a um projeto comum em .NET. Podemos adicionar novos itens, outras classes, referenciar outros projetos e muito mais. Neste exemplo, a referência ao serviço já foi adicionada ao projeto. Também por padrão é adicionado um certificado temporário para que o projeto possa ser aceito pelo Office.

Antes de prosseguir é preciso esclarecer alguns pontos – vamos focar esta seção mais no Excel, mas as perguntas e respostas são válidas para outros programas.

  1. O que é o VSTO? O VSTO nada mais é do que o conjunto de ferramentas necessário para se trabalhar com o Excel utilizando o .NET. É composto de bibliotecas de classes, ferramentas gráficas e customizações do Excel necessárias para que o Add-in seja reconhecido e corretamente visualizado no Excel. Também é responsável por se comunicar com os objetos COM do modelo do objetos do Excel e realizar adequadamente as ações desejadas. E por fim, o VSTO possui um conjunto interessante de eventos trazidos do Excel para o .NET, de forma que é possível saber no .NET quando por exemplo, alguém altera uma determinada célula da planilha.
  2. Como eu faço para conhecer o modelo de objetos do Excel? Para trabalhar com a automação é necessário ter noção de como se cria macros no VBA. Uma macro do Excel pode ser transcrita para o C# com certa simplicidade.  O modelo de objetos está muito bem documento na ajuda do VBA. Para mostrar a tela do VBA do Excel, use ALT + F11. Finalmente, use o Gravador de Macros do Excel para ir aprendendo os comandos e sintaxe mais comuns do Excel.
  3. Vejo alguns namespaces que estão me confundindo. Para se trabalhar com o Excel, temos as bibliotecas principais representadas por Microsoft.Office.Interop.Excel e Microsoft.Office.Core. Essas bibliotecas contêm basicamente uma representação em .NET do que o Excel contém. Elas são os famosos PIAs. Se na tela do VBA você achar um objeto denominado Chart, no objeto equivalente em .NET você provavelmente também encontrará o Chart. Vale notar que as traduções em .NET são feitas com interfaces e não classes concretas em .NET. Mas na prática, você conseguirá controlar o objeto da mesma forma, chamando os métodos com os mesmos nomes e parâmetros vistos no VBA. Porém, existe um outro namespace que mora em outra biblioteca do VSTO denominada Microsoft.Office.Tools.Excel. Este último namespace guarda objetos em .NET que representam os principais recursos do Excel em .NET, melhorados de forma a se tornarem particularmente úteis. Eles contém uma representação bacana do Workbook, Worksheet, ListObject, NamedRange e alguns outros elementos. Tais elementos podem ser criados diretamente do .NET usando o designer do Visual Studio, muito similar à criação de um controle utilizando Windows Forms. Com isso, o desenvolvedor tem como referenciar de forma simplificada os objetos importantes de sua planilha.
  4. Qual o melhor jeito de começar com os testes simples? O ideal é trabalhar com o Globals. Esta classe contém uma referência para todos os objetos do Tools.Excel de forma simples. Para acessar a planilha1, basta pedir Globals.Sheet1 e por aí vai… vamos mostrar na prática como funciona a referência a tais objetos. Brinque com o Range, com o Offset, modifique os conteúdos da célula… Para rodar basta utilizar o F5 comum para fazer os testes. O add-in é carregado e o Visual Studio consegue se atachar ao código .NET que está executando na planilha. Logo, é possível colocar breakpoints no VS2010 e olhar o que está em cada variável. Também é possível utilizar janelas como Immediate Window para realizar testes preliminares sobre a validade de suas expressões. O desenvolvimento para Office exige uma carga adicional de tentativa e erro para realizar uma determinada tarefa. E com o Visual Studio você tem total suporte a isso. Recomendamos que você tenha calma pois muitas vezes poderá acontecer um erro de COM impossível de descobrir pelo fato de não se ter um modelo legal de controle de erros como o .NET. Não se assuste. Vá por partes. Tenha certeza que cada pedaço da expressão funcionou. Lembre-se de não usar índice zero com o Range e laços For. Use e abuse do Immediate Window. Use Listas e Named Ranges – evite lógica com o número/nome da range. Por fim, domine o Excel.
  5. E o Ribbon? Como trabalhar com ele? O Ribbon, que é o menu inovador lançado no Office 2007, também continua presente no Office 2010. Na verdade, ele foi ligeiramente modificado no Office 2010 – foi criado um “Backstage Ribbon” no 2010, que contém opções que geralmente ficariam no menu Arquivo. Esse backstage ribbon se chama File na versão americana do Office. No .NET, é um controle que pode ser adicionado ao projeto, com um code-behind contendo eventos convenientes. No designer do VS2010 é possível arrastar e soltar itens para o Ribbon e amarrar eventos a cada botão de forma normal, como se fosse em Windows Forms. Para o desenvolvedor, o Ribbon é uma aba que fica no dentro do menu Add-ins do Excel. E para o desenvolvedor, o Ribbon nada mais é que um form cheio de controles comuns. Simples e prático de usar. O Ribbon pode ser criado mesmo em customizações de documentos. Não necessariamente vale só para customização de aplicações.

Antes de prosseguir com a customização, fizemos um teste básico para ver se realmente era possível chamar o WCF de dentro do Excel. Embora isso pareça ser óbvio, não necessariamente tudo acontece conforme o esperado. No evento que é chamado quando o arquivo abre, colocamos o seguinte teste:

image

Entretanto, ocorreu um erro. Ao dar F5, o Excel tenta abrir:

image

Mas em seguida surgiu uma mensagem de erro:

image

image

Conforme esperado, o conjunto de dados era maior do que o padrão (conforme visto nos testes). Deixamos este erro acontecer para demonstrar que quando o erro acontece você pode parar, debugar e continuar com a execução. Não recomendamos que você mate o processo dando stop na depuração. Sempre continue com F5 e só então termine a execução. As falhas podem acontecer e quando acontecem, o Excel lança o erro neste formato mostrado acima e continua normalmente a rodar, sem cair.

Finalmente acertamos o config da aplicação e testamos novamente com sucesso.

image

Trazendo dados do WCF para o Excel

Tendo a certeza de que o WCF estava trazendo os dados e que o Excel é capaz de mostrar os dados, vamos para o próximo passo: mostrar os produtos na planilha do Excel.

Para isso, crie uma nova tabela na planilha principal com 2 colunas. Assuma que as colunas terão um header. Como as tabelas devem ter um nome, nós alteramos para tblProdutos:

image

Esta funcionalidade se chama “Tabela” no Office 2007 em diante. No Office 2003 esta funcionalidade se chama “Lista”. Por isso que no .NET ela também se chama ListObject. Com o uso de tabelas, os dados ficam muito mais organizados do que em planilhas comuns, sendo uma forma muito inteligente de trabalhar com dados no Excel, mesmo quando não estamos fazendo coisas tão avançadas como Macros e customizações com .NET.

O próximo passo é criar o Ribbon, que será mostrado ao usuário final e terá alguns itens para podermos realizar nossos exemplos. Ao escolher a opção Add New Item do projeto Excel, no VS2010 aparecerá vários itens. Vá no subgrupo Office e escolha a opção Ribbon (Visual Designer). É possível criar um Ribbon editando um arquivo XML específico diretamente – modo avançado de se trabalhar com o Ribbon.

image

O editor visual mostra o Ribbon vazio. Devem ser adicionados os controles ao Ribbon usando o designer visual por ser mais prático.

image

Com o Ribbon pronto, vamos fazer o código busca a lista no WCF e faz o databind com o ListObject do VSTO/Table do Excel. O código que executa é um evento do click do botão de dentro do Ribbon. Logo, ele não está em nenhuma planilha. Portanto é preciso referenciar os objetos de interesse utilizando a classe Globals. Vejamos como fazer isso:

image

A classe Globals é gerada automática pelo template do VS2010 e representa como propriedades estáticas os objetos importantes do documento Excel. O Sheet1 é uma representação melhorada da planilha para uso em .NET e não o Sheet do Interop. O tblProdutos é um campo do objeto .NET Sheet1.

O método SetDataBinding permite fazer o databind com qualquer conjunto de dados comum do .NET. No caso, este método possui a capacidade de escolher quais colunas podem ser mostradas ou não. O segundo parâmetro está vazio, mas por exemplo, poderia ser o nome da tabela que esteja dentro do Dataset no caso de múltiplas tabelas.

Com o databinding, eu consigo colocar os dados na lista sem ter que me preocupar com o número de linhas na lista, redimensionamento e sem ter que usar um laço For para processar cada registro. Muitos incômodos a menos. Com isso a lista preenchida fica conforme mostra a figura abaixo. O Ribbon tem mais 2 botões que serão úteis para os testes seguintes em cima da lista preenchida. Note que o Ribbon que montamos ficou dentro da aba Add-Ins. Nesta aba ficam também os outros add-ins de fabricantes diversos.

image

Trabalhando com os dados obtidos no Excel utilizando C# 4.0

A nossa Ribbon agora deverá ter mais dois botões conforme mostrado na tela acima. No designer ela fica assim:

image

O botão “Trabalhar com Lista” irá mostrar os 10 primeiros registros da lista. Desta forma poderemos ver algumas novidades que o C# 4.0 tem para nos ajudar nesta tarefa.

Antes de mostrar o método completo temos que comentar sobre os objetos dinâmicos do C#. Veja a imagem abaixo extraída do Intellisense:

image

Se você observar bem, o objeto correspondente a uma Range específica é do tipo dynamic. Isto é, não precisamos fazer um cast para o objeto exato do Interop para poder trabalhar com o objeto desejado. Note também que em C# antes era obrigatório passar o Type.Missing para os parâmetros opcionais e agora não é mais – ele já vem com o valor pré-fixado para nossa conveniência.

Para ser mais completo na explicação, o Range possui um indexer com o parâmetro coluna e linha opcionais. Isso significa que posso ter vários tipos de seleção de conjunto de células e na prática, vários tipos de retornos do mesmo indexer. Para isso é conveniente a assinatura com parâmetros opcionais e retorno dinâmico, pois mais tarde o desenvolvedor, que já espera qual será o retorno adequado, pode trabalhar com o resultado esperado sem se preocupar em tempo de compilação. Abaixo segue a assinatura do indexer da classe Range do Interop.Excel – o Range normal não foi evoluído no Tools.Excel. Só o NamedRange.

image

Voltando então ao exemplo, decidimos deixar o método mais prolixo para explicitar o uso do dynamic do C# 4.0:

image

Neste caso, embora não fosse necessário para este exemplo, fizemos com que a cada iteração do For, o Range equivalente à linha da lista de produtos ficasse guardado numa variável dinâmica. A partir deste momento, tudo o que for feito com a variável x também se torna dinâmico, permitindo que eu chame métodos e realize atribuições sem saber exatamente o que tem em x com a ajuda do Intellisense. Se eu quisesse chamar uma propriedade x.Teste, só iria dar erro em tempo de execução. O compilador, ao lidar com variáveis dinâmicas, não tem como descobrir quais são os métodos e propriedades de x. Mas como conhecemos o modelo de objetos, as variáveis valorColuna1 e valorColuna2 ficarão com os valores adequados. Finalmente, o método Append do StringBuilder saberá qual overload usar para inserir o número ou o nome do produto.

Finalmente, com um último exemplo mais prático, vamos mostrar todos os código de produto recebidos pelo serviço num MessageBox. Com isso vamos mostrar que também é possível iterar com foreach de forma mais prática em alguns casos. Podemos usar dynamic diversas situações como mostra a figura a seguir.

image

Executando os dois exemplos temos os seguintes resultados:

a) Primeiros 10 itens da lista:

image

b) Todos os códigos de produto recebidos do serviço:

image

Com isso conseguimos concluir como mostrar e trabalhar com dados no Excel, concluindo assim o exemplo.

Conclusão

Com esta pequena demonstração conseguimos mostrar como trabalhar com fontes de dados modernas como web services, por exemplo. O uso de VBA, embora seja bastante válido e muito poderoso, não permite que se use arquiteturas mais modernas nem ferramentas de desenvolvimento mais atualizadas para se criar aplicações atuais para a plataforma Microsoft Office.

O uso da plataforma Office está crescendo muito e os desenvolvedores hoje precisam entender que nem todo sistema precisa ser Web! Muitas vezes, uma solução muito mais complicada em Web pode ser facilmente resolvida utilizando o Office com inteligência.

O uso de .NET e Visual Studio 2010 também favorece muito o desenvolvimento de aplicações baseadas em Sharepoint, o que torna o uso do Excel, do Word e do Outlook particularmente importante como plataforma de desenvolvimento de aplicações corporativas. Com vários templates para Sharepoint, é possível criar solução altamente integradas com custos muito menores de desenvolvimento, utilizando ferramentas que os information workers conhecem há mais de 10 anos – a plataforma Microsoft Office.

Sobre Nós

A Accendis é uma consultoria que presta serviços utilizando a plataforma de desenvolvimento Microsoft. Conheça mais sobre o nosso trabalho www.accendis.com.br. Se você precisar de treinamento para você, sua empresa, alocação de profissionais em formato body shop e consultoria para resolver problemas mais complexos, estamos aqui para te ajudar.

Grande Abraço

Equipe Accendis

, , , , , , ,
Adicionar aos Favoritos BlogBlogs Adicionar esta notícia no Linkk

Introdução

Este artigo visa demonstrar como o uso de serviços em aplicações .NET podem te ajudar a criar aplicações distribuídas modernas.

Para uma idéia de como funcionam aplicações web modernas, veja o artigo anterior que mostra como criar começar a organizar a sua solução para começar a trabalhar.

Vamos falar sobre Web Services, Windows Communication Foundation, configurações típicas para sistemas Web e aplicações distribuídas. Vamos também falar um pouco sobre as tendências da Microsoft para a exposição de dados na forma de serviços modernos.

Onde Estamos?

Você criou uma aplicação Web. Ela entrou em produção na sua empresa. Você ganhou reconhecimento e notoriedade no ambiente de trabalho devido ao aumento de velocidade na obtenção de métricas. Muitos ficaram sabendo que as informações que o seu sistema gera são confiáveis. Outras áreas concorrentes viram outras oportunidades de redução de custos operacionais. Um e-mail chega:

“Olá! Nós precisamos muito de sua ajuda! O sistema ABC que você criou está nos economizando muito tempo, porém, ainda tenho que fica digitando o resultado dos seus cálculos no sistema XYZ que você criou no ano passado… Não tem como você fazer com que os dados apareçam automaticamente?”

Atualmente o sistema se apresenta para o cliente no formato Web clássico. Ele é muito útil, porém, é útil para seres humanos compreenderem as informações. Entretanto, outro sistema não consegue entender e processar os dados gerados nos seus relatórios. E agora o que fazer?

Para você que já está no mercado, a solução é quase óbvia: por que não usar Web Services?

Web Services

Web Services são lugares públicos conhecidos na rede (na internet, intranet, porta tcp local) que são capazes de expor uma informação com base num pedido. No caso acima, o sistema XYZ, que usa os dados do sistema ABC, deveria fazer uma requisição ao Web Service hospedado em algum endereço conhecido do sistema ABC. O sistema ABC recebe a requisição e dá a resposta em um formato combinado entre as partes.

Aí você que está começando pode se perguntar: “Não entendi bem, afinal, qual é a diferença entre um site normal da Web e um Web Service?”. A resposta prática para esta questão é a seguinte: um site comum da web retorna tudo o que pode aparecer no browser, como imagens, HTML, animações e demais itens. O Web Service funciona da mesma forma, usando os mesmos protocolos de rede e os mesmos caminhos, mas retorna apenas, no caso geral, um XML contendo os dados de interesse. Ambos possuem um endereço na internet/intranet. Neste exemplo, é possível ter o site, www.abc.suaempresa.com.br para hospedar o site correspondente ao sistema ABC. Para hospedar o Web Service do sistema abc, seria possível criar um endereço na intranet de nome www.abc.suaempresa.com.br/webservice.

Assim como browsers conseguem ler HTML, sistemas feitos .NET, Java e demais linguagens conseguem traduzir tudo o que está exposto no Web Service e com isso, conseguem se comunicar com o mesmo. Existe um protocolo padrão da indústria para a comunicação utilizando Web Services, que é o SOAP. Ao definir um Web Service, podemos definir as operações (posso receber comandos) e posso definir o tipo de dados o Web Service utiliza (por exemplo, podemos definir entidades complexas como por exemplo, a classe Pessoa). Também é possível definir outros parâmetros diversos, como a obrigatoriedade de certos parâmetros/valores, etc..

O processo de “tradução” do conteúdo de um Web Service geralmente é automático em todas as tecnologias da atualidade – inclusive em .NET. O Visual Studio consegue ler o que está no Web Service e gerar métodos e classes “proxy", que imitam o que o serviço faz dando a impressão para o desenvolvedor de que a chamada de um certo método é local.

Em várias plataformas de desenvolvimento, a comunicação entre sistemas utilizando Web Services é a forma padrão de se integrar sistemas diversos. E quando falamos de integração entre sistema de diversos fornecedores com diversas tecnologias, a forma mais simples de se conseguir uma integração é utilizando Web Services mesmo. Porém, para os desenvolvedores que utilizam a plataforma .NET., esta tecnologia é considerada obsoleta a partir do surgimento do .NET Framework 3.0 e 3.5, que trouxeram e consolidaram no mercado uma maneira mais completa de se trocar dados entre sistemas que rodam em Windows: Windows Communication Foundation.

Windows Communication Foundation

A Microsoft sempre disponibilizou para seus desenvolvedores um grande conjunto de opções para realizar quase sempre árdua tarefa de fazer 2 sistemas trocarem dados entre si. Com o advento do WCF, a Microsoft unificou e simplificou todos os tipos de tecnologias numa única tecnologia mais completa, simplificada e muito madura no momento da escrita desde post, Janeiro de 2010.

Com o WCF temos algumas boas vantagens:

  • Não somos obrigados a comunicar utilizando SOAP via HTTP
  • Qualquer aplicação pode ser servidor para o WCF, isto é, não preciso de um servidor Web para nenhum tipo de tarefa
  • Posso contar com recursos do Windows para ativar o serviço com a chegada de uma nova mensagem
  • Temos grande liberdade para determinar como será a passagem de mensagens de um lado para o outro. Temos controle sobre a segurança, formato das mensagens, transações, confirmação de recebimento de uma mensagem, filas de mensagens e também, podemos interferir diretamente sobre a mensagem recebida ou enviada. Podemos ter comunicações em 2 sentidos, coisa que nem sempre é fácil de ser implementada.
  • Flexibilidade para configurar o serviço, muitas vezes, evitando que qualquer linha de código seja escrita.
  • Não é necessário aprender Remoting, COM+, Enterprise Services, etc… – basta aprender o conceito de Web Services e o WCF em si.

Na prática, a maior parte das pessoas utilizam e utilizarão WCF para trocar mensagens SOAP via HTTP. A grande vantagem que vemos no uso do WCF é a possibilidade de se criar um projeto “Windows Service” (*.exe) para hospedar o meu serviço em WCF. Com isso, ganha-se a possibilidade de controle total, ainda mais quando o sistema tem chances de cair. Um serviço WCF hospedado no IIS, em alguns casos, pode ser prejudicial em caso de falha. Mas cada situação é diferente e para cada caso é necessário realizar uma análise completa da arquitetura para enfim decidir a melhor forma de hospedagem.

Qualquer tipo comum de projeto pode hospedar o WCF e quase qualquer tipo de aplicação .NET consegue fazer referência a um servço existente. Até mesmo aplicações como Office, Silverlight e Sharepoint trabalham bem com WCF.

Camadas de serviços modernas

Para o caso de aplicações atuais, o WCF é peça fundamental na arquitetura de um sistema orientado a serviços ou mesmo, para aplicações distribuídas.

Utilizando um mesmo serviço (ou conjunto de serviços) você pode fazer com que o sistema atenda a diversos tipos de clientes tais como Windows, Web, Celulares, Aplicações RIA (Flash / SIlverlight), Office, etc… Todos eles conseguem se conectar à mesma fonte de informação de forma uniforme, centralizando num único ponto as fontes de dados e possivelmente, de regras de negócio da aplicação como um todo.

Ao adicionar um serviço à solution do Visual Studio, você está na prática adicionando uma camada de serviços à sua aplicação. Como já falamos anteriormente, é preciso ter atenção e evitar qualquer camada desnecessária interferindo no fluxo de dados principal da aplicação. Mas, após as devidas análises terem sido feitas, você estará construindo uma aplicação com a possibilidade de ser distribuída, isto é, você ganha a capacidade de criar vários clientes para acesso dos mesmos dados. No caso de aplicações RIA, não há outra forma de se fazer acesso a dados sem ser por intermédio de uma camada de serviços, por questões de segurança da Web.

Consideramos como moderna uma camada de serviços criada sem restrições quando à forma de hospedagem, forma de lidar com as mensagens e principalmente, com a forma de passar os dados pelo “channel” ou canal de informações. Em .NET, somente o WCF consegue oferecer este tipo de capacidade para o desenvolvedor. Com o uso de WCF, o cliente pode referenciar o serviço da mesma forma que é referenciado um Web Service hoje em dia.  Porém para ser moderna a camada de serviços também precisa ser capaz de expor os dados de forma atualizada. Isto significa que os serviços de “hoje em dia” devem expor os dados em formato REST também. Outra funcionalidade também é a utilização de dados em formato JSON, XML e mesmo, serializados conveniente de forma binária para otimização de banda. O WCF possui tecnologia para endereçar todos estes requisitos. A Micrososft está adotando o padrão de acesso e manipulação de dados OData (Open Data Protocol), que basicamente uniformiza a forma de acessar e recuperar dados entre as diversas fontes de dados da internet de hoje em dia.

Tecnologias que devemos considerar para criar camadas modernas de serviços

 

Entity Framework

O EF foi lançado na versão 3.5 SP1 do .NET Framework. Ele é voltado para acelerar e mesmo, revolucionar aplicações que utilizam o banco de dados SQL Server. Como uma ferramenta ORM, ele evita que seja necessário criar um camada de acesso a dados formal para fazer operações do dia-a-dia. O EF gera um modelo de dados que é então utilizado pelas aplicações que o utilizam para realizar consultas utilizando o LINQ para gerar consultas diretamente ao modelo. Com esta consulta ao modelo, o EF gera o SQL e retorna / modifica os dados desejados. É possível utilizar stored procedures dentro do modelo de dados.

O EF no .NET Framework 4.0 está foi radicalmente melhorado, com suporte a cenários n-camadas melhorado e com muito mais funcionalidade para auxiliar os desenvolvedores a gerar modelos de dados customizados, lazy loading, suporte a entidades simples (sem o overhead do controle de alterações do EF) e ampliado suporte a mapeamento em cenários mais complicados que foram sugeridos pelos clientes. E finalmente, será possível desenhar primeiro o modelo de entidades da aplicação para então gerar o banco de dados correspondente, coisa que é possível com o NHibernate há tempos.

A grande desvantagem na época da escrita deste artigo, Janeiro/Fevereiro de 2010, é que não há providers gratuitos para quem trabalha com Oracle, Postgree e MySQL ainda. O que se sabe é que há chance de surgir um provider gratuito para MySQL. Há empresa que oferecem providers pagos, mas não conhecemos ninguém que utilize os mesmos (por favor me corrijam se eu estiver errado).

O Entity Framework é a tecnologia base para tecnologias que também utilizam o WCF como transporte, a saber: WCF RIA Services e o WCF Data Services.

WCF Data Services (antigo ADO.NET Data Services)

O Data Services serve para expor um modelo de dados do Entity Framework através de uma interface REST. O DS é uma extensão do WCF (isto é, pode ser hospedado como qualquer serviço WCF). É uma tecnologia que visa facilitar o acesso a dados tanto de aplicações Web comuns como AJAX, como Silverlight e .NET.

Para expor os dados via WCF Data Services, é preciso que se tenha uma fonte de dados que suporte consultas utilizando LINQ, isto é, que implemente IQueryable/IUpdatable. Resumidamente, a aplicação pede um endereço para o serviço, e este endereço é traduzido como uma consulta LINQ para que então, o provedor de dados retorne os dados de interesse.

Na prática, o DS serve para facilitar muito a vida de quem programa e cria serviços usando WCF. Com o WCF puro, é possível fazer tudo. Com o Data Services, temos uma facilidade muito maior para manipular os dados de forma que não seja necessário invocar métodos específicos para atualizar cada entidade do modelo de dados. E na prática, esta facilidade é conseguida criando um modelo de dados com o Entity Framework e expondo-o com o WCF Data Services.

Esta tecnologia, existe há mais de 2 anos, está evoluindo bastante e virá com novas features como por exemplo, paginação e ordenação via servidor. Considera-se que para que seja o padrão dos desenvolvedores ainda há um caminho a ser percorrido.

WCF RIA Services

O RIA Services é uma tecnologia que surgiu com o Silverlight 2 para simplificar o acesso das aplicações feitas em Silverlight a um serviço WCF. Por segurança, as aplicações RIA (Flash e Silverlight) só podem acessar um serviço caso o mesmo esteja no mesmo domínio da aplicação web que hospeda a aplicação RIA.

Uma aplicação web hospeda a aplicação Silverlight em um domínio. Geralmente o serviço não está no mesmo projeto da Web, isto é, está em um outro projeto, ou mesmo, outra solução do Visual Studio. Neste caso é preciso que o serviço permita que a aplicação Silverlght o acesse utilizando um arquivo de permissões (crossdomain.xml e/ou clientaccesspolicy.xml, por exemplo). Isto é, o servidor onde mora o serviço do WCF a ser acessado precisa ter estes arquivos configurados.

Com o uso do RIA Services, consegue-se um middle-tier de modo que o serviço acabe ficando no mesmo domínio da aplicação Silverlight. Mas esta não é a única vantagem. A tecnologia é muito semelhante ao WCF Data Services. É possível disparar do cliente queries usando LINQ, processar e retornar os dados definidos em um modelo de dados do Entity Framework. Com o RIA Services, o desenvolvedor Siverlight consegue quase tudo o que precisa para entregar um projeto e coloca-lo rapidamente no ar. Ele possui facilidades como paginação, ordenação, filtragem, validação, coisas que facilitam muito para o desenvolvimento.

O RIA Services é destinado quase que exclusiva ao uso de clientes Silverlight e por enquanto não houve a convergência com o Data Services. Mas a intenção da Microsoft parece ser o investimento no ecossistema de tecnologias destinadas a serviços da web, pois afinal, a web está mais focada em serviços do que nunca.

Opções de projeto com o Visual Studio

Uma das grandes vantagens de se usar o WCF quando você criar a solução completa, isto é, os clientes e os serviços, é que você pode compartilhar bibliotecas entre as diversas camadas. Esta possibilidade permite que você use as mesmas classes do serviço, no cliente. Ou seja, a entidade “Pessoa” é sempre definida na mesma dll, que é chamada tanto de uma aplicação web como de um serviço WCF. Isto pode ser bom em situações onde o domínio é mais rico e contém métodos, herança e demais complicadores que podem não ser corretamente expostos pelo serviço em si.

Porém, este tipo de técnica é mais benéfica em aplicações web do que em aplicações mais ricas, como WPF, Windows e Silverlight. O grande problema de compartilhar os objetos de negócio é a necessidade de distribuição das dlls todas as vezes que a versão muda. E para aplicações distribuídas, é recomendável manter a regra de negócios no lado do serviço já que todo o código que roda no cliente pode ser de alguma forma visto e pode sofrer processo de engenharia reversa. Numa aplicação ASP.NET, a lógica da aplicação ainda fica no servidor, impedindo que a lógica da aplicação circule pela internet, vindo para o cliente apenas código Html/CSS e Javascript.

Com o surgimento do Entity Framework, surgem novas opções de projeto. Podemos simplificar as coisas de modo que a Solution do Visual Studio fique flexível para atender a diversas situações.

Vamos propor aqui uma solução mais purista na parte de serviços. Desta forma, vamos evitar dependências com tecnologias que ainda estejam mudando, como é o caso do WCF RIA Services e do WCF Data Services. Vamos utilizar o Entity Framework como tecnologia de acesso a dados, e vamos também, propor alguns clientes que fazem acesso à camada de serviços.

Vamos lá!

Camada de acesso a dados:

Não será necessário criar a camada de acesso a dados de forma clássica. O Entity Framework expõe ao modelo de dados para as camadas de negócio e assume a responsabilidade de invocar a infraestrutura do ADO.NET (e por conseguinte, tabelas,views e procedures do banco de dados SQL Server 2005/2008). Vale lembrar ao usar Oracle ou outro banco de dados, faz mais sentido usar outra ferramenta como o NHibernate. O mesmo vale para aplicações multi-banco de dados. Há a opção com do LINQ to NHIbernate, que pode ser uma boa saída para manter os benefícios de se usar LINQ contra o modelo de dados mapeado pelo NHibernate.

Camada de negócios:

Nesta proposta de separação de camadas, vamos simplificar um pouco as coisas. Como já vamos utilizar o Entity Framework para fazer o acesso a dados, vamos centralizar na mesma biblioteca as regras de negócios e as entidades da aplicação. As entidades do sistema são as mesmas geradas pelo EF. Caso o modelo de dados não forneça todas as propriedades necessárias, ou caso seja necessário adicionar métodos às nossas entidades geradas pelo modelo, iremos utilizar classes parciais para complementar as entidades da aplicação.

Na mesma dll mas em pastas diferentes, poderemos definir as regras de negócio e algumas classes utilitárias. Claro que para projetos maiores e mais complexos pode fazer sentido quebrar essa camada de negócios em mais bibliotecas.

Vale ressaltar aqui que, com o lançamento do EF do .NET 4.0, você tem a capacidade de controlar o mapeamento e a geração de classes automática do EF, permitindo que se use modelos de dados cada mais inteligentes nos mapeamentos. Também será possível criar o banco e dados a partir da definição do modelo de dados, tudo isso de dentro do Visual Studio.

Camada de serviços:

Vamos utilizar a camada de serviços como o ponto de encontro da nossa aplicação. Ela acessará a camada de negócios, fazendo o meio-de-campo entre os dados do servidor e as solicitações dos clientes diversos, que acessarão o serviço WCF. Neste projeto, vamos pensar numa arquitetura mais robusta e portanto, vamos hospedar o serviço em um Windows Service, para ter total controle sobre o que acontece com o serviço. O IIS7 possui várias funcionalidade interessantes para a parte de serviços, mas nossa experiência mostra que quando o serviço está propenso a erros ou quando ele exige uma quantidade maior de memória e processamento, o servidor Web pode não ser o host mais adequado. Porém, como muitos de nós utiliza hospedagem compartilhada, a hospedagem em IIS pode ser a única opção.

Clientes: ASP.NET, Silverlight e WPF

Os clientes poderão fazer referência direta apenas ao serviço neste modelo de solução proposto. Eles não poderão ter acesso a mais nenhuma dll das camadas acima. Para a utilização de Silverlight em aplicações de negócios, recomenda-se também o padrão de projetos MVVM, que busca criar aplicações mais testáveis e com lógica de negócios mais separada possível da lógica de apresentação.

Para o caso de aplicações ASP.NET clássicas ainda acreditamos que faz sentido criar uma DLL compartilhada entre o serviço e a Web. Neste caso específico, não temos grandes problemas com deploy e local de armazenamento da regra de negócios no caso simples, onde o serviço e a web estão na mesma solution e fazem parte do mesmo processo de Deploy.

Conclusão

O uso de WCF ainda está sendo descoberto pelas empresas não só do Brasil, mas do mundo. Há muita coisa pronta feita em Web Services “normais” do .NET e inclusive, novos projetos ainda hoje são criados são criados usando esta tecnologia considerada legada pela Microsoft, mas não ainda pelo mercado. O grande argumento para a não migração é a falta de pessoal capacitado para utilizar esta nova tecnologia. Entretanto, é preciso que os arquitetos connheçam esta importante opção de projeto principalmente, quando o simples não é o suficiente para uma determinada situação.

Para nós da Accendis, o uso de WCF é mainstream nos projetos em que atuamos e consideramos que esta é a tecnologia base para várias inovações da Microsoft em um horizonte de 1 a 3 anos.

, , , ,
Adicionar aos Favoritos BlogBlogs Adicionar esta notícia no Linkk

Introdução

Este artigo visa demonstrar alguns conceitos básicos para você que está começando a trabalhar profissionalmente com .NET e se encontra no seguinte momento da carreira: “Vou começar um projeto do zero, qual é a melhor forma de se trabalhar?”

Vamos apresentar alguns tópicos interessantes sobre o conceito de camadas e noções de arquitetura de sistemas empresariais comuns. Vamos discutir de forma simplificada como os conceitos se relacionam, para que de fato, você consiga ter um norte para começar a desenvolver um projeto. E por fim, vamos demonstrar como tudo isso acontece organizando os projetos no Visual Studio 2008. No final do artigo temos o exemplo completo para download.

Conceitos Iniciais: Perguntas e Respostas

  1. Ouço muito falar em desenvolvimento n-camadas. Mas exatamente o que são camadas?
    É praticamente um consenso no mercado a separação do software em camadas. Para saber quais são as camadas físicas da aplicação, basta fazer a seguinte pergunta: “Em quais máquinas meu sistema irá rodar?”. Como respostas comuns, a vasta maioria das aplicações em .NET rodam em um servidor Web com o auxílio de um servidor de banco de dados. Portanto, temos 3 camadas físicas rodando em 2 máquinas: Apresentação (servidor web), Regras de negócio (servidor web) e Persistência (servidor de banco de dados e servidor web).

    Outras correntes de pensamento julgam que o número de camadas é proporcional ao número de componentes que podem rodar independentemente. Por exemplo, no caso acima, se tivéssemos também um Windows Service com o qual a parte web se comunicasse, teríamos uma quarta camada. Mesmo que o serviço rode na máquina da web.  Ou seja, na prática, o que vale mesmo é o número de “pedaços de software independentes” que fazem alguma coisa. Podemos dizer que a camada de negócios é independente pelo fato que ainda é possível rodar apenas a lógica de negócios sem a necessidade da camada de apresentação através de técnicas simples como testes unitários, por exemplo.

    Camadas lógicas são grupos de funcionalidade geralmente reutilizáveis, mas que não conseguem rodar dentro de um contexto isoladamente. Por exemplo, podemos falar em camada de acesso a dados: tal camada lógica pode ser chamada de um serviço do WCF, de uma aplicação Web clássica ou então, de uma aplicação Windows comum. Uma camada física pode conter várias camadas lógicas. Por exemplo, a camada de negócios pode conter uma camada de regras de negócio, outra camada de controle de segurança, etc…  Mas necessariamente estão no fluxo de dados principal da aplicação.

    Resumindo, camada é todo o “pedaço de software” que participa do fluxo de dados principal da aplicação. Caso o “pedaço de software” não participe mandatoriamente do fluxo de dados principal, mas é sempre utilizado de alguma forma, provavelmente estamos em vista do que chamamos de componente.

  2. O que são componentes na prática?
    Componentes são conjuntos de classes e funções agrupados por funcionalidade similar, que podem servir a qualquer tipo de propósito e podem ser chamados por qualquer outra camada, componente ou mesmo, várias camadas e componentes. Geralmente  os componentes são pensados com o reuso em mente. Inclusive, geralmente vemos que as empresas se preocupam mais em criar componentes do que camadas reutilizáveis. Na prática, ao criar uma camada de acesso a dados, não temos como reutilizar em outro projeto totalmente diferente. Porém, um componente de controle de exceções ou componente de envio de e-mail é sempre reutilizável.
  3. O que são aplicações corporativas na prática
    Aplicações corporativas são aquelas onde a sua razão de existir se justifica pela real necessidade de resolver um problema da empresa. Simples assim. Ela serve para otimizar algum processo interno, podendo ter uma criticidade alta e também, podendo ser responsável por causar grandes prejuízos à empresa caso ela não esteja no ar. Podemos afirmar que na prática, todas as aplicações corporativas trabalham com banco de dados em algum momento. Aplicações não-corporativas são aquelas que na prática são úteis apenas para uma pessoa e não para um conjunto de pessoas ou então, no caso de jogos, servem para diversão. Tais aplicações podem ser muito mais complexas ou muito mais simples do que aplicações corporativas e quase sempre são pensadas de formas totalmente distintas de uma aplicação corporativa.

Cuidados importantes

O desenvolvimento em múltiplas camadas exige que o desenvolvedor/arquiteto tenha muito senso de organização. Nós da Accendis já presenciamos vários equívocos. Vamos a eles:

  1. Não exagere no número de camadas! Utilize o mínimo de camadas necessário para que a aplicação funcione hoje e amanhã, quando for preciso criar novas funcionalidades. Quanto maior o número de camadas, maior será a lentidão da aplicação, pois os dados deverão atravessar mais obstáculos do que o necessário.
  2. Não tenha medo de separar em camadas! Há uma grande quantia de sites que usam apenas um projeto Web para fazer tudo do sistema. Tudo! Outras equipes usam o mesmo Windows Service (.exe) para colocar todas as regras de negócio do sistema, tornado-o impossível de debugar. O maior erro dos desenvolvedores é não pensar na testabilidade do código, isto é, provar de jeito simples que o código funciona. E depois, o Visual Studio é bem prático para se trabalhar com vários projetos. Como outras vantagens, temos maior clareza e organização, e no caso onde há controle de versão, quanto maior o número de arquivos e projetos, mais divisíveis são as tarefas.
  3. Evite adotar padrões de projeto prontos que são facilmente encontrados na web. Não é por que parece ser lindo usar alguns tipos de elementos de arquitetura que você realmente precisará usar. O exemplo mais clássico disso é o fato de se usar uma camada de regras de negócio que na prática, só serve pra chamar a camada de acesso a dados.
  4. Não confunda os papéis das camadas! Evite colocar regras de negócio nas páginas de code-behind. Evite colocar nas regras de negócio componentes que podem ser reutilizáveis… Enfim, use o bom senso!
  5. Use e abuse do conceito de Namespaces. Separe classes similares em pastas. Esta dica é especialmente importante para código VB.NET, onde a lógica de namespaces é confusa para os recém-chegados.
  6. Geralmente se cria 01 projeto para cada camada lógica da aplicação. Não se recomenda juntar camadas num mesmo projeto (isto é, uma DLL com mais de uma função geral). Não se recomenda também criar vários projetos para um propósito similar.
  7. Cuidado ao utilizar padrões novos/avançados de projeto, como por exemplo, inversão de controle, arquitetura de plugins ou suporte a script. Use tais recursos somente se for absolutamente necessário e se todos os riscos de fracasso estiverem controlados. O mesmo vale para arquiteturas Web 2.0, como RIAs, MVC, etc… Atualmente, a escolha da tecnologia da camada de apresentação acarreta em alterações profundas na arquitetura do sistema com um todo. O fluxo de dados se modifica radicalmente. O maior risco é a falta de conhecimento dos desenvolvedores, que já são obrigados a absorver as novidades tecnológicas em uma velocidade estonteante. Mas, sempre esteja informado sobre novidades arquiteturais, pois as mesmas podem causar uma drástica redução da carga de trabalho. Um grande exemplo é o uso do Entity Framework ou NHibernate.
  8. Refactoring não é crime! Não tenha medo de alterações grandes no seu projeto! Projetos são feitos para resolver o problema do business. Como o problema a ser resolvido pode mudar com o tempo, seu projeto e sua arquitetura também podem ser influenciados. Por exemplo, podemos ter uma página da web com alguma funcionalidade que precise também estar presente em aparelhos móveis. Obviamente as mudanças são necessárias no número de camadas, nas formas de trocas de mensagens, etc. Outro exemplo pode ser a remoção de uma camada de acesso a dados antiga feita em ADO.NET clássico para evoluir com o LINQ ou NHibernate. Outras vezes, você ser surpreendido com a necessidade de suportar mais de um banco de dados na mesma aplicação. As coisas mudam. Não seja resistente a mudanças. Aproveite!

Arquitetura básica de um projeto Web em ASP.NET

Os projetos web de hoje em dia são relativamente complexos. E projetos de grande porte geralmente acompanham serviços, executáveis e demais acessórios para realizar tarefas diversas que não sejam apenas respostas a requisições da Web.

Porém, de alguma forma tais aplicações estendem ou imitam o padrão. Basicamente, quando se usa .NET, a receita de bolo é a seguinte, mas não necessariamente a mais “profissional” ou “correta”:

  1. [Camada de apresentação] Crie um projeto do tipo “Web Application” no Visual Studio. Não crie o projeto como “Web Site” pois esta decisão acarreta em várias dificuldades em criar funcionalidade comum a todas as páginas e causa dificuldades grandes ao referenciar dlls de outros projetos.
  2. [Camada de negócios] Para a camada de negócios, geralmente se cria um projeto do tipo “Class Library” para conter regras de negócios e outra “Class Library” para conter as entidades da aplicação. Portanto devem ser criados 2 projetos. Vale relembrar que os projetos do tipo “Class Library” são bibliotecas que quando compiladas viram DLLs comuns.
  3. [Camada de acesso a dados / Persistência] No mínimo sua aplicação terá que acessar os dados de alguma forma. Os dados podem ser expostos pelo banco em forma de tabelas, views ou stored procedures. Para isso, você terá que escrever ou usar outra solução que automatize o processo de criação de métodos para se comunicar com o banco. Crie um projeto do tipo “Class Library” para o projeto de acesso a dados também.
  4. [Componentes] Crie uma biblioteca de componentes utilitários. Este projeto deverá conter componentes úteis para todas as camadas. No caso real, pode haver mais projetos de componentes.
  5. [Testes Unitários] Crie uma biblioteca para guardar testes unitários. Para isso, é preciso ter alguma versão do Visual Studio que suporte a criação de testes unitários ou então, usar o NUnit para criar os testes.

Com isso, vamos acabar com uma solution com 6 projetos, ainda isolados entre si. Vamos discutir sobre como referenciar os projetos dentro da solution.

  1. Todas as camadas devem referenciar a DLL de entidades da aplicação.
  2. O projeto de testes unitários deverá referenciar todos os projetos da aplicação, com exceção do projeto Web.
  3. O projeto Web referencia a DLL de negócios.
  4. O projeto de negócios referencia a DLL de acesso a dados.
  5. Todos os projetos, inclusive o de testes unitários, poderão referenciar a DLL de componentes, à medida da necessidade.

O diagrama conceitual da Solution do Visual Studio fica com o mostrado nas figuras abaixo. Como nós da Accendis já passamos por vários projetos em várias empresas, uma das tendências que encontramos foi a nomenclatura em inglês de namespaces, classes e métodos. Mas na prática, muitas pessoas acabam misturando as nomenclaturas para que o nome fique o menor possível. O maior argumento para usar nomenclatura em inglês é o fato de haver chances de vender o sistema para algum comprador internacional, tendo como premissa que o cliente final deverá ter condições de manter o código.

Na imagem abaixo estão os detalhes de cada projeto a ser criado:

Lista de todos os projetos a serem criados no Visual Studio

Lista de todos os projetos a serem criados no Visual Studio

Nesta imagem abaixo, podemos ver um desenho mostrando as dependências entre cada projeto:

Relacionamento entre os diversos projetos da Solution do Visual Studio

Relacionamento entre os diversos projetos da Solution do Visual Studio

Conclusão

Com esta noção inicial de como organizar um projeto, como referenciar projetos e soluções, você está pronto para começar a entender ou mesmo criar um projeto empresarial Web comum de médio porte. Entretanto, este modelo muitas vezes pode ser estendido com mais pedaços de software, como Web Services, Windows Services e mesmo, alguma camada de aplicação RIA, como Silverlight ou Flex.

Antes de encerrar este artigo, queremos deixar claro que quase sempre compensa fazer este tipo de solução, com componentes separados em camadas. O que se vê por aí é que o projeto começa pequeno, cresce desordenadamente e fica impossível de se trabalhar com o tempo. Logo, o tempo inicial para montagem da solução compensa o esforço de refactoring futuro.

Para baixar esta solução de exemplo, clique aqui para obter a solução em formato zip, utilizando Visual Studio 2008 Team System e compilado em .NET Framework 3.5 SP1. No projeto de testes, referenciamos a DLL NUnit.Framework.

Dúvidas, Sugestões, Reclamações ou Dicas? Comente!

Grande abraço!
Mário Meyrelles (http://twitter.com/mariomeyrelles)
Equipe Accendis

, , ,
Adicionar aos Favoritos BlogBlogs Adicionar esta notícia no Linkk


Introdução

Para prosseguir com nossos estudos sobre o Entity Framework, vamos falar agora das operações básicas de select com as entidades do modelo de dados. Para seguir por esse exemplo, é necessário que você tenha lido o artigo anterior explicando como foram feitas etapas do projeto. Clique aqui para acessar o artigo inicial desta série.

Os testes unitários nesta fase do projeto não serão tão rigorosos, com inúmeras asserções e casos de falha – nosso objetivo é a praticidade e a velocidade no aprendizado.  Vale lembrar que é necessário um conhecimento básico de LINQ para conseguir progredir nestes exemplos. Neste artigo vamos aprender como fazer consultas básicas com WHERE e ORDER BY.

Executando comandos SELECT simples.

Nesta série de exemplos iremos criar testes que apenas buscam dados do banco de dados. Com isso teremos uma notável sensação de economia de tempo ao ver que é possível modificar à vontade o método de acesso a dados sem ter que ficar escrevendo tediosos comandos SQL.

Vamos relembrar do artigo passado como fizemos o nosso primeiro SELECT no banco. Se você seguiu o que foi sugerido no artigo passado, o banco deverá ter 3 registros na tabela Unidade:

using System;
using System.Collections.Generic;
using System.Linq;
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 fechados
            //após o termino da execução 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);
            }
        }
    }
}

Vamos explicar em detalhes este método. Primeiramente, é criada uma classe do contendo o atributo [TestFixture]. Este atributo indica que esta classe poderá ter vários testes unitários. O atributo [Test]  indica que o método ListarUnidades() é um teste unitário. Como regra geral, as classes de teste não podem ter construtores customizados (com parâmetros) e os métodos de teste devem ser do estilo “void-no-args”, isto é, não podem retornar nada e não devem possuir parâmetros.

O bloco using mostra criação de uma instância de uma conexão ao contexto de dados do entity framework. Seria equivalente a preparar um SqlCommand. Ele usa como parâmetro uma connection string especial (que você vê em detalhes no seu app.config do projeto de testes). Neste caso, usamos uma classe e método estático que acessa o arquivo de configuração e nos retorna os dados desejados sem grande esforço.

Dentro do bloco using, podemos montar nossa consulta utilizando LINQ à vontade. Neste caso, fizemos um comando equivalente a um SELECT * na tabela Unidade do banco de dados. Nós poderíamos ter feito uso da palavra chave “var” e rescrito a linha de comando assim:

//Não utilizar este padrão!
var unidades = from u in entities.Unidade select u;

Este comando também funcionaria e então poderíamos realizar o mesmo foreach abaixo. Esta alternativa é válida em casos simples mas no caso genérico, onde é necessário retornar um objeto para as camadas superiores da aplicação, o ideal é fazer a materialização da lista chamando o método ToList(). Com uma lista formalizada, é possível realizar quais e quantas operações eu quiser.

O Entity Framework retorna as consultas do banco de dados de forma que elas sejam apenas enumeráveis uma única vez. Lembrem-se disso. Só é possível ler o resultado de uma mesma consulta uma única vez! Com a lista não – é possível ler quantas vezes quisermos. Nos códigos seguintes sempre usaremos este padrão, que é usar lista fortemente tipada e evitando ao máximo o uso do “var”. Aliás, o uso do “var” fora de consultas com LINQ é uma péssima prática de programação quando se fala em C#.

O foreach final percorre os registros recebidos e mostra na tela de resultados do plugin de testes unitários que o ReSharper oferece. Vale lembrar que esta ferramenta é opcional. E no caso geral, não é necessário imprimir os resultados de testes unitários, pois a idéia é que os mesmos sejam automáticos no futuro.

Um fato imporante é o pedaço do código: entities.Unidade – esta propriedade representa um objeto do tipo ObjectQuery. Esta classe na prática implementa IQueryable e IQueryable, que no fim das contas são as interfaces que quando implementadas fazem o trabalho de transformar queries do LINQ em comandos SQL possíveis de serem executados. Cada entidade possui uma propriedade criada de forma automática.

A última linha indica uma asserção. Todos os frameworks de testes unitários oferecem um conjunto de asserções para que o teste unitário faça a checagem se uma determinada condição é verdadeira ou falsa. Caso seja falsa, o teste falha e indica que houve uma falha de asserção.
Agora que já sabemos como é um teste unitário básico, vamos progredir com os exemplos de select simples.

        [Test]
        public void ListarUnidadesWhere()
        {
 
            using (GerFacEntities entities = new GerFacEntities(AppConfiguration.ConnectionString))
            {
 
                List unidades = (from u in entities.Unidade where u.Descricao == "Unidade 2" select u).ToList();
                foreach (Unidade unidade in unidades)
                {
                    Console.WriteLine(string.Format("{0} - {1}", unidade.Nome, unidade.Descricao));
                }
                Assert.IsTrue(unidades.Count() == 0);
 
                unidades = entities.Unidade.Where(u => u.Nome == "Unidade 2").ToList();
                foreach (Unidade unidade in unidades)
                {
                    Console.WriteLine(string.Format("{0} - {1}", unidade.Nome, unidade.Descricao));
                }
                Assert.IsTrue(unidades.Count() == 1);
            }
        }

O exemplo acima contém duas formas de se fazer uma consulta com where. A primeira usa a sintaxe chamada pela comunidade de “query syntax”, que se assemelha muito a consultas SQL comuns. A sua leitura é bem simples. A segunda consulta mostra como realizar a consulta utilizando Lambda Expressions entrada do método Where e sua sintaxe é conhecida como “fluent syntax / method syntax / full query syntax”. As consultas geradas pelo EF são as mesmas independentemente da sintaxe utilizada. Também é possível misturar sintaxes, pois no fim, o compilador analisa e monta as expressões lógicas necessárias.

Finalmente, vamos falar de ordenação e o que pode acontecer ao buscar uma única entidade do banco. Veja o teste abaixo:

        [Test]
        public void ListarUnidadesOrderbyNull()
        {
            using (GerFacEntities entities = new GerFacEntities(AppConfiguration.ConnectionString))
            {
                List unidades = (from u in entities.Unidade
                                          where u.Nome == "Unidade 2"
                                          orderby u.ID descending
                                          select u).ToList();
 
                Assert.IsTrue(unidades.Count() > 0);
 
                Unidade unidadeInexistente = (from u in entities.Unidade
                                              where u.Nome == "Unidade 4"
                                              select u).First();
                Assert.IsNull(unidadeInexistente);
 
            }
        }

A primeira consulta contém um comando de ordenação simples e passará pela primeira asserção. Já a segunda consulta irá causar a exceção já que não temos a Unidade 4 no banco. Com isso acontece a seguinte falha:

Exceção no Resharper

Este erro é causado pelo fato de se buscar a primeira entidade de uma lista que não contém elementos. Este erro é evitável utilizando usando o método “FirstOrDefault” no lugar de “First”. Com este método, é possível retornar valores nulos da consulta sem problemas. O método corrigido fica assim:

        [Test]
        public void ListarUnidadesOrderbyNull()
        {
            using (GerFacEntities entities = new GerFacEntities(AppConfiguration.ConnectionString))
            {
                List unidades = (from u in entities.Unidade
                                          where u.Nome == "Unidade 2"
                                          orderby u.ID descending
                                          select u).ToList();
 
                Assert.IsTrue(unidades.Count() > 0);
 
                Unidade unidadeInexistente = (from u in entities.Unidade
                                              where u.Nome == "Unidade 4"
                                              select u).FirstOrDefault();
 
                Assert.IsNull(unidadeInexistente);
 
            }
        }

Os comandos que buscam dados do banco podem ser mais complexos do que os exemplos acima. Porém, com o que já temos é possível realizar grande parte das buscas simples do dia-a-dia e provavelmente você estará fazendo este tipo de consulta 70% do tempo.

Encorajamos você a pesquisas os métodos que passaram a ser disponibilizados a partir da versão 3.5 do .NET. Navegue pelos métodos disponibilizados pelas entidades do modelo, tais como entidade.Unidde, entidade.Aluno e etc. Com esse background sua a experiência será cada vez maior.

No próximo artigo vamos falar sobre as operações de modificação de dados. Até já!

,
Adicionar aos Favoritos BlogBlogs Adicionar esta notícia no Linkk


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 LINQPá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.

  1. Cadastro básico: Nome, Formas de Contato
  2. 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

  1. O sistema deverá suportar o envio de mensagens para os alunos da turma
  2. 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

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

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.

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

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

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

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)

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!

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

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.

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

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.

,
Adicionar aos Favoritos BlogBlogs Adicionar esta notícia no Linkk