Introdução

Criação e codificação de formulários é uma das principais tarefas no desenvolvimento de aplicativos ASP.NET. Normalmente as informações digitadas precisam ser validadas para que os dados processados ou armazenados na base sejam obrigatoriamente válidos.

Nos tempos do ASP clássico, boa parte das tarefas da validação eram realizadas através de JavaScript. Apenas os profissionais muito caprichosos tinham a cautela de realizar a validação TAMBÉM no servidor. Esse procedimento se faz necessário pela possibilidade do usuário desabilitar o uso de JavaScript em seu navegador e com isso não estar sujeito a validação.

No ASP.NET existem controles específicos para validação que fazem parte do Microsoft .NET Framework. Esses controles realizam a validação nos dois lados da aplicação: cliente e servidor. Nesse post falarei dos mais utilizados, porém se você precisar de mais alguma informação que não encontrou aqui acesse a página que explica os controles detalhadamente no MSDN: http://msdn.microsoft.com/pt-br/library/debza5t0.aspx

RequiredFieldValidator

O tipo de validação mais comum é fazer com que um determinado campo tenha conteúdo obrigatório. Para esse tipo de validação deve-se utilizar o controle RequiredFieldValidator.

Assim como todos os controles que vamos exemplificar nesse post, o RequiredFieldValidator se encontra no grupo Validation da Toolbox.

Para utilizar esse controle você deverá realizar as seguintes configurações:

Nome:
<asp:RequiredFieldValidator ID="rfvNome" runat="server"
     ControlToValidate="txtNome" ValidationGroup="Cadastro"
     ErrorMessage="O campo nome é obrigatório">
</asp:RequiredFieldValidator>
<br>
<asp:TextBox ID="txtNome" runat="server"
     ValidationGroup="Cadastro">
</asp:TextBox>
<br>
<asp:Button ID="btnSalvar" runat="server"
     Text="Salvar" ValidationGroup="Cadastro">
</asp:Button>

Como resultado desse exemplo você obterá uma validação de campo obrigatório atuando no campo Nome. Se o usuário apertar o botão Salvar sem ter informado algum valor no campo Nome a mensagem “O campo nome é obrigatório” será exibida.

RegularExpressionValidator

Digamos agora que nossa necessidade é verificar se a informação inserida em um campo atende a um critério pré-estabelecido.

Para solucionar esse problema utilizaremos o controle RegularExpressionValidator. Através de uma expressão regular que será configurada no controle faremos a validação da informação.

Em nosso exemplo vamos verificar se um endereço de e-mail é válido. Nesse exemplo para simplificar o código escrevi apenas o bloco do RegularExpressionValidator deixando de lado o TextBox e o Button que são necessários para o teste completo.

<asp:RegularExpressionValidator ID="revEmail" runat="server"
     ControlToValidate="txtEmail" ValidationGroup="Cadastro"
     ErrorMessage="Endereço de e-mail inválido."
     ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
</asp:RegularExpressionValidator>

O resultado desse exemplo é a validação do endereço de e-mail atuando no campo E-mail. Se a informação digitada não for válida após a validação do formulário será exibida a mensagem “Endereço de e-mail inválido”.

ValidationSummary

Em formulários muito extensos é muito comum que o desenvolvedor necessite exibir em um único lugar todas as mensagens de erro de validação. Para essa finalidade existe um controle chamado ValidationSummary.

A sintaxe para uso desse controle é bastante simples e prática:

<asp:ValidationSummary ID="vlsCadastro" runat="server"
     ValidationGroup="Cadastro" />

Com o uso desse controle, após a validação serão exibidos no local desejado todas as mensagens de erro de validação.

Esses são os três principais controles utilizados na validação de formulários ASP.NET. Como sempre, espero que esse post seja de grande ajuda para a comunidade de desenvolvedores .NET.

Um grande abraço a todos!

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

Introdução

Durante as tarefas de desenvolvimento de aplicativos ASP.NET é muito comum a necessidade de recuperar variáveis relacionadas ao servidor e também aos caminhos físicos e relativos da página atual.

Devido a essa constante necessidade estou escrevendo esse post que explica as principais variáveis de servidor do objeto Request.

APPL_PHYSICAL_PATH

Utilizada para recuperar o caminho físico onde está configurado o servidor de aplicação.
Por exemplo: C:\Inetup\wwwroot\Sites

AUTH_USER

Recupera o nome do usuário autenticado.
Por exemplo: ACCENDIS\Aubry Maciel

PATH_INFO

Utilizado para recupear o endereço relativo desde a pasta inicial do servidor de aplicação até o nome da página atual.
Por exemplo: /sites/treinamentos/promocoes.aspx

PATH_TRANSLATED

Retorna o caminho físico completo do arquivo correspondente a página atual.
Por exemplo: C:\Inetpub\wwwroot\sites\treinamentos\promocoes.aspx

Exemplo de utilização

Para acessar os valores contidos nessas variáveis é muito simples. As variáveis estão armazenadas dentro do objeto Request dentro de uma lista chamada ServerVariables.

    Request.ServerVariables["PATH_INFO"]

Não citei e exemplifiquei todas as variáveis existentes pois a lista é um pouco extensa e nem todas tem a mesma relevância. Para complementar o post e permitir que você possa se aprofundar mais segue uma lista com todas a variáveis.

ALL_HTTP ALL_RAW APPL_MD_PATH
APPL_PHYSICAL_PATH AUTH_TYPE AUTH_USER
AUTH_PASSWORD LOGON_USER REMOTE_USER
CERT_COOKIE CERT_FLAGS CERT_ISSUER
CERT_KEYSIZE CERT_SECRETKEYSIZE CERT_SERIALNUMBER
CERT_SERVER_ISSUER CERT_SERVER_SUBJECT CERT_SUBJECT
CONTENT_LENGTH CONTENT_TYPE GATEWAY_INTERFACE
HTTPS HTTPS_KEYSIZE HTTPS_SECRETKEYSIZE
HTTPS_SERVER_ISSUER HTTPS_SERVER_SUBJECT INSTANCE_ID
INSTANCE_META_PATH LOCAL_ADDR PATH_INFO
PATH_TRANSLATED QUERY_STRING REMOTE_ADDR
REMOTE_HOST REMOTE_PORT REQUEST_METHOD
SCRIPT_NAME SERVER_NAME SERVER_PORT
SERVER_PORT_SECURE SERVER_PROTOCOL SERVER_SOFTWARE
URL HTTP_CONNECTION HTTP_ACCEPT
HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_HOST
HTTP_USER_AGENT

Espero que esse post ajude você em seus estudos!

Até a próxima. Um abraço a todos!

,
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() &gt; 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 =&gt; 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() &gt; 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() &gt; 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() &gt; 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