"Nunca deixe para o tempo de execução o que pode ser feito em tempo de compilação."
David Gries, Construção de Compiladores para Computadores Digitais
Introdução
Como programadores, quando estamos aprendendo algumas novas tecnologias, os exemplos às vezes podem ser nossos maiores inimigos. As diretrizes geralmente são projetadas para serem simples e fáceis de entender, mas ao mesmo tempo podem levar a um aumento na escrita de código preguiçosa, ineficiente e até perigosa. A situação mais comum como esta está no paradigma ADO.NET. Neste artigo, veremos o que significa ter objetos fortemente tipados em um banco de dados, permitindo que você faça isso em seus programas, apesar da falta de exemplos.
Um pouco mais especificamente, veremos como conjuntos de dados fortemente tipados são criados e usados no Visual Studio 2005. Conforme explora este artigo, conjuntos de dados com tipagem forte oferecem muitas vantagens em relação a outra técnica de acesso a dados com tipagem fraca. Também veremos aqui que criar e usar conjuntos de dados fortemente tipados não fica mais fácil com o Visual Studio 2005. Se você quiser saber mais, continue lendo.
Os princípios básicos e os benefícios dos objetos de tipagem forte
Para entender o que significa digitação forte, você pode primeiro pensar em namoro. Se você fosse solteiro, que tipo de pessoa você consideraria namorar? Você pode ter critérios específicos (como ser saudável e atraente) ou os critérios podem ser simples ou pouco claros. Não importa quais sejam suas condições, ao decidir com quem passar mais tempo, você sempre usará seus próprios padrões para esses tipos pesarem e considerarem. Se você for inteligente, pensará muito para se proteger de traumas emocionais. Você pode descobrir que, por exemplo, estar com um alcoólatra é instável, a menos que os dois estejam em um relacionamento sério. No entanto, é doloroso e muito difícil fazer uma pessoa mudar. Portanto, sua sabedoria irá instruí-lo a interromper o relacionamento antes mesmo de começar. Adicionar uma cláusula de proibição de beber aos seus critérios de namoro irá protegê-lo de futuras dores de cabeça e permitir que você concentre seu tempo e energia em melhores candidatos.
Você pode se surpreender com o quanto esse raciocínio tem a ver com programação. Não importa, venha comigo, querido leitor! Os objetos de acesso a dados ADO.NET são projetados para serem extremamente flexíveis. Ao ler dados de um banco de dados, você provavelmente estará trabalhando com muitos dos tipos comuns de objetos permitidos pela estrutura .NET normal, a menos que encontre problemas especiais. Aplicando nossa teoria de datação, você pode basicamente pensar nos seus dados relevantes como objetos universais. "Contanto que meu encontro não seja muito problemático." Não há limite, mesmo que seja um humano ou outra criatura viva! Como seu amigo, imploro: "Mais padrões! Diminua sua lista!"
Assim como negligenciar quem você namora pode levar a problemas de relacionamento no futuro, deixar seus objetos desmarcados em seu código também pode causar erros. Além disso, se você deixar objetos antigos vagarem pela sua sub-rotina, poderá não perceber que isso é um problema até que o programa esteja em execução. Para usar nossa teoria do namoro, detectar erros em tempo de execução é como fazer com que seu acompanhante tenha uma discussão dolorosa e estranha no meio de um restaurante italiano da moda. Sim, veja bem, se você tivesse planejado com antecedência, não teria acabado com um bando de clientes olhando para você e não teria sido constrangedor. Simplesmente aplicando alguns padrões mais rígidos ao seu código, você pode detectar erros antes que o programa comece a ser compilado. Por exemplo, o exemplo de código a seguir:
string FirstName = myrow.("FirstName").ToString();
O DataRow neste exemplo não é digitado e, como resultado, você deve usar o nome da coluna como uma string para obter o valor necessário (ou pode optar por usar o índice da coluna na coleção de colunas do registro). Felizmente essa coluna existe. O tipo de dados da coluna DataRow é objeto. Assumimos que o tipo de dados na coluna FirstName é string e devemos convertê-lo explicitamente em string antes de usá-lo. Se o nome desta coluna for alterado (por exemplo, se tornar PersonFirstName), o compilador não terá como notificá-lo. Deprimido? Mas você não precisa. Se o seu código for semelhante ao seguinte, sua vida será mais simples e seu código será mais confiável.
string FirstName = PersonRow.FirstName
Neste segundo exemplo, usamos uma linha fortemente digitada e sabemos que a propriedade FirstName é do tipo string. Sem nomes de colunas confusos, sem conversões de tipo confusas. O compilador já fez a verificação de tipo para nós e podemos realizar outros trabalhos com segurança, sem nos preocupar se digitamos os nomes das colunas corretamente.
Todo o resto é igual, então você não hesitará em usar isso em vez do tipo genérico. Mas espere um minuto, de onde vêm os objetos fortemente digitados? Também gostaria de poder dizer que esses objetos são criados automaticamente. Mas assim como bons relacionamentos exigem tempo e esforço, tornar seus objetos fortemente tipados exige um esforço extra. Mas o tempo extra gasto aqui definitivamente vale a pena e economiza exponencialmente mais tempo gasto na “captura de bugs” no futuro.
Existem várias maneiras de realizar uma digitação forte e passaremos o restante deste artigo explicando como criar um conjunto de dados com tipagem forte no Visual Studio 2005. Também compararemos as vantagens e desvantagens desta abordagem com outras abordagens.
Criando conjuntos de dados fortemente tipados no Visual Studio 2005
Conjuntos de dados fortemente tipados são, na verdade, apenas colunas e tabelas predefinidas de conjuntos de dados comuns, portanto, o compilador já sabe o que eles contêm. Em vez de um invólucro solto que cabe em você como uma luva de beisebol, conjuntos de dados fortemente tipados cabem como uma luva. Cada versão sucessiva do Visual Studio facilita o manuseio de conjuntos de dados com rigidez de tipos. No exemplo a seguir, usaremos o banco de dados AdventureWorks do SQL Server 2005. Basta seguir estas etapas:
1. Abra o Visual Studio e crie um novo site ASP.NET.
2. Na janela Solution Explorer, clique com o botão direito para adicionar um novo item e selecione DataSet. Nomeie-o como AdventureWorks.xsd (veja a captura de tela). O Visual Studio recomendará que você coloque o arquivo DataSet no arquivo App_Code e basta clicar em Concordo.
3. Após abrir AdventureWorks.xsd no modo de design, o assistente de configuração do TableAdapter será executado. Neste ponto, clique em Cancelar e arrastaremos a tabela desejada do Server Explorer.
4. Navegue para localizar o banco de dados AdventureWorks na barra de ferramentas do Server Explorer. (Se você não instalou o banco de dados AdventureWorks, você pode ir para a página de download da Microsoft Amostras e bancos de dados de exemplo do SQL Server 2005 para baixá-lo e alguns outros exemplos do SQL Server 2005)
5. Arraste a tabela SalesOrderHeader e a tabela SalesOrderDetail para a janela de design do DataSet. A janela deve ser semelhante à da captura de tela. O que estamos vendo? Sempre que adicionarmos uma tabela, o Visual Studio criará um DataTable fortemente tipado (com o mesmo nome da tabela original) e um TableAdapter. Este DataTable definiu cada coluna para nós. TableAdapter é o que usamos para preencher a tabela. Por padrão, existe um método Fill() para obter cada linha de dados da tabela original.
Do jeito que está, esse conjunto de dados fortemente tipado retornará todos os registros de ambas as tabelas. Mas o banco de dados AdventureWorks contém muitas informações sobre pedidos, então por que não criar uma consulta mais explícita? Podemos adicionar métodos ao objeto TableAdapter para obter um conjunto de subregistros específico. Clique com o botão direito em SalesORderHeaderTableAdapter e selecione Adicionar|Consulta. Selecione "Usar instruções SQL" e clique em Avançar, selecione "SELECIONAR que retorna linhas" e clique em Avançar. Recentemente, insira a seguinte consulta na janela (ou você pode usar o Query Builder para fazer o trabalho):
SELECIONAR
SalesOrderID, RevisionNumber, OrderDate, DueDate, ShipDate,
Status, OnlineOrderFlag, SalesOrderNumber, PurchaseOrderNumber,
Número da conta, ID do cliente, ID do contato, ID da pessoa de vendas, ID do território,
BillToAddressID, ShipToAddressID, ShipMethodID, CreditCardID,
CreditCardApprovalCode, CurrencyRateID, SubTotal, TaxAmt, Frete,
TotalDue, comentário, rowguid, ModifiedDate
FROM Sales.SalesOrderHeader
ONDE (OrderDate > @OrderDate)
Esta consulta SQL é uma consulta SELECT simples, usando um parâmetro @OrderDate para filtrar os resultados. Isso nos evitará retornar todos os registros do banco de dados. Mantenha as caixas de seleção "Preencher um DataTable" e "Retornar um DataTable" selecionadas e clique em Concluir. Depois de adicionar esta instrução SELECT, seu designer agora deve se parecer com a captura de tela, com uma consulta adicional em SalesOrderHeaderTableAdapter.
Depois que o conjunto de dados fortemente tipado for estabelecido, podemos exibir facilmente os dados na página ASP.NET com algumas linhas de código. Crie uma nova página ASP.NET no site e mude para o modo de design. Arraste um controle GridView para ele e deixe seu ID como GirdView1. Em seguida, vá para a página de código-fonte e introduza o namespace AdventureWorksTableAdapters acima do arquivo (a sintaxe em c# está usando AdventureWorksTableAdapters;). Por fim, adicione o seguinte código ao evento Page_Load:
//Cria o SalesOrderHeaderTableAdapter
SalesOrderHeaderTableAdapter salesAdapter =
new SalesOrderHeaderTableAdapter();
// Obtém os pedidos ocorridos após 1º de julho de 2004
Pedidos AdventureWorks.SalesOrderHeaderDataTable =
salesAdapter.GetDataBy(new DateTime(2004, 7, 1));
// Vincula os resultados do pedido ao GridView
this.GridView1.DataSource = Pedidos;
this.GridView1.DataBind();
O código é muito simples. Criamos uma instância de SalesORderHeaderTableAdapter para preencher a tabela de dados. O que deve ser observado aqui é que, diferentemente de um DataTable comum, declaramos um objeto do tipo SalesORderHeaderDataTable. Chamamos o método GetDateBy() e passamos um objeto DateTime para preencher os dados. Observe também aqui que o comando obtido também é fortemente digitado, portanto devemos passar um objeto DateTime em vez de um objeto comum. A captura de tela abaixo é o resultado do exemplo de código acima.
Além de usar código para vincular o conjunto de resultados ao GridView, você também pode usar um ObjectDataSource, definir sua propriedade TypeName como AdventureWorksTableAdapters.SalesOrderHeaderTableAdapter e definir seu SelectMethod como GetData ou GetDataBy.
Além de não precisar escrever código para se conectar ao banco de dados, outra grande vantagem de usar um conjunto de dados fortemente tipado é que não há strings de nomes de colunas escondidas em nosso código que o compilador não possa verificar. Também não precisamos fazer nenhuma conversão de tipo. Se o esquema do banco de dados for alterado, basta atualizar o arquivo AdventureWorks.xsd e descobriremos que todas as alterações relacionadas serão concluídas automaticamente em tempo de compilação.
Outras técnicas para gerar aplicações de acesso a dados com tipagem forte
Além de usar conjuntos de dados com tipagem forte, existem outras maneiras de implementar tipagem forte em seus programas. Você pode criar classes personalizadas que sejam mais leves que DataSets e mais consistentes com seu banco de dados. Existem também alguns desenvolvedores de software terceirizados que desenvolveram ferramentas para automatizar esse processo. Um dos mais especiais e meu favorito é o LLBLGen Pro. Certa vez, escrevi um livro sobre ele: Rapid C# Windows Development: Visual Studio 2005, SQL Server 2005 e LLBLGen Pro. (Você pode ler 1/3 do livro gratuitamente no meu site.) Outra ferramenta popular é o CodeSmith. Até a Microsoft está desenvolvendo uma pequena ferramenta chamada DLINQ, mas ela ainda está em testes e estima-se que só será lançada pelo menos no próximo ano.
Se você usar a forte abordagem de conjunto de dados do Visual Studio, uma das vantagens inegáveis é que você não precisa adquirir software adicional. Todas essas soluções têm recursos e benefícios diferentes, mas os principais benefícios são confiabilidade, menos erros e menos tempo gasto na depuração. Também é mais fácil verificar o impacto das alterações no esquema do banco de dados e realizar manutenção. Esperamos que você tenha percebido os benefícios de uma digitação forte. Boa sorte com o desenvolvimento (e com o namoro também)!
Por Joseph Chancellor
Anexos
Baixe o código examinado neste artigo
Sobre o autor
Joseph Chancellor é um desenvolvedor C# no sul da Califórnia que já teve seu quinhão de traumas relacionais. Ele aprecia todos os tipos de comentários e sugestões. Visite seu blog ou leia os primeiros cinco capítulos de seu livro sobre Visual Studio 2005, SQL Server 2005 e.
do LLBLGen
: http://aspnet.4guysfromrolla.com/articles/020806-1.aspx