Migrando do ADO “Clássico” para o ADO.NET

Um extrato do Hitchhiker's Guide to Visual Studio and SQL Server 2005 (7th Edition)

William Vaughn
Beta V Corporation

Agosto de 2005

Aplica-se a:

  • Microsoft ADO.NET

  • Microsoft SQL Server 2005 (codinome "Yukon")

  • Microsoft Visual Studio 2005 (codinome "Whidbey")

Resumo: Bill Vaughn discute o processo de conversão de código em ADO do Visual Basic 6.0 para código que possa ser usado em um aplicativo .NET para executar basicamente as mesmas operações. (11 páginas impressas).

Nesta página

Por que esse caminho é necessário?
Como chegamos até aqui?
Migrando habilidades de desenvolvimento do ADO Clássico
Novidades do ADO.NET 2.0
Quais são as alternativas?
Conclusão

Nota do autor: Há quase um ano, a Microsoft me pediu para escrever um artigo que ajudasse os desenvolvedores do ADO baseado em COM a entenderem os problemas e a mecânica para portar o código de acesso a dados para o .NET. Este ano eles querem que eu atualize esse artigo com informações sobre o ADO 2.0. Como estou trabalhando no momento em uma nova edição de meu Hitchhiker's Guide, pensei em simplesmente extrair um trecho do novo capítulo e apresentá-lo aqui.

O Hitchhiker's Guide to Visual Studio and SQL Server 2005 (7th Edition) será publicado pela Addison Wesley depois do lançamento do Whidbey e do Yukon para fabricação.

Meus agradecimentos a Calvin, Haroldo e Bill Waterson: fiquei fascinado com o termo "metamorfosear" por algum tempo. Essa tecnologia (aparentemente) existe por algum tempo e propositalmente foi usada para descrever o processo de transformar sapos em príncipes e bonecos em pessoas (ou vice-versa). Mas usarei o termo metamorfosear para fazer referência ao processo de conversão do código em ADO do Visual Basic 6.0 em código que possa ser usado em um aplicativo .NET para executar basicamente as mesmas operações. O termo metamorfosear indica que o resultado da conversão será muito pouco reconhecível em relação à fonte original e, nesse caso, é totalmente apropriado assumir que o código em ADO baseado em COM (do Visual Basic 6.0) é convertido totalmente em ADO.NET. Não, algumas pessoas não acham que essa seja uma grande mudança, mas eu acho, pelas razões que discutirei aqui.

Por que esse caminho é necessário?

Depois de ter "consertado" minha bicicleta de três marchas no quintal em uma tarde ensolarada, meu pai sugeriu que eu não devia "consertar" coisas que não estão quebradas. Concordo totalmente. Não faz sentido mexer em código funcional a menos que haja uma razão convincente para isso e você tenha feito uma análise racional do custo-benefício. Por "racional" quero dizer uma análise que não implique em um apelo de vendas emocional (talvez feito por seu gerente de desenvolvimento ou pelo primo de terceiro grau de sua esposa), mas baseada em uma análise profunda das despesas incorridas para criar, desenvolver, testar, implantar e oferecer suporte a seus aplicativos, além da despesa para treinar seus desenvolvedores novamente e para oferecer suporte à equipe e aos fornecedores. Você também pode incluir os custos de quaisquer atualizações de hardware necessárias para executar o Framework e seu novo aplicativo. Como você sabe, converter código ou mesmo ajustá-lo pode ser uma tarefa onerosa. Mesmo que você tenha cuidado, cada linha alterada pode ter conseqüências e efeitos colaterais enormes (normalmente involuntários). Fora isso, em muitos casos, há razões suficientes e lógicas para se converter o código existente, por exemplo:

  • Talvez o código existente não possa tirar proveito de aprimoramentos do hardware ou do SO. Por exemplo, seu código pode ter sido criado para funcionar com o Windows 9x (e possivelmente só com ele) e seus clientes evoluíram para o Windows XP.

  • Talvez o código existente não seja tão competitivo, pois outras empresas criaram substituições mais rápidas, confiáveis e fáceis de vender para seus aplicativos. Isso acontece o tempo todo, à medida que nossos clientes se esforçam para manter a liderança em recursos, funcionalidades e preços competitivos.

  • Talvez o novo aplicativo pudesse ser mais bem dimensionado, oferecer suporte a mais usuários, ser mais seguro ou mais fácil de implantar ou simplesmente capaz de implementar recursos não disponíveis com a tecnologia existente.

  • Talvez seus clientes reclamem da maneira como seu código parece funcionar por um tempo e depois passa a apresentar falhas, principalmente depois que alguém instala outro software.

  • Talvez (e provavelmente o mais importante) você descubra que a nova plataforma de desenvolvimento possa melhorar sua capacidade de criar novos aplicativos e oferecer suporte ao código e aos clientes que o usam com uma equipe menor.

Não vou entrar no processo da tomada de decisão de sair de uma base de código existente em direção ao horizonte atrativo da nova tecnologia. Essa decisão deve ser feita por sua equipe de TI. Se você estiver lendo este artigo para obter uma dica sobre a mecânica da conversão do código em ADO baseado em COM existente (que eu chamo de "ADO Clássico" ou ADOc) para a execução em um aplicativo do Visual Basic .NET, continue lendo.

Como chegamos até aqui?

Com o passar dos anos, a Microsoft introduziu uma dinastia de interfaces de acesso a dados. No início, elas foram criadas para acessar versões específicas do DBMS da JET (Joint Engine Technology) e do SQL Server (via biblioteca de banco de dados). À medida que a tecnologia amadureceu, outras interfaces "genéricas" ou de tamanho padronizado como ODBC e OLE DB foram criadas para acessar virtualmente todas as fontes de dados do planeta. O ADO baseado em COM (que eu chamo de ADOc) foi criado para permitir acesso fácil ao OLE DB.

O ADO "Clássico" evolui

Com o tempo, o ADOc evoluiu e, oito versões mais tarde, ele é amplamente usado e integrado ao Visual Basic baseado em COM. Os desenvolvedores do ADOc também aprenderam a criar aplicativos que gerenciam bancos de dados grandes e pequenos e são usados em arquiteturas de cliente/servidor, de camada intermediária e de ASP no mundo inteiro. O ADOc também foi bem aceito por oferecer suporte a procedimentos armazenados (incluindo o gerenciamento completo de parâmetros de ES), geração automática de consultas de atualização, operações assíncronas, cursores do lado do cliente e do servidor, fluxos de dados de RO/FO e muito mais. O ADO baseado em COM também tinha seus problemas. Sua dependência da pilha do MDAC o tornava propenso a problemas com DLLs e, à vezes, os aplicativos implantados apresentavam falhas quando o MDAC era atualizado.

O ADO.NET é introduzido

Para resolver o problema da necessidade de substituição de componentes de aplicativos em funcionamento, a Microsoft inventou o .NET Framework. Além disso, ela criou também uma interface completamente nova de acesso a dados, o ADO.NET. No início do processo de criação do ADO.NET, os desenvolvedores da Microsoft chamavam sua nova interface de acesso a dados de "XDO". Isso porque esse novo paradigma de acesso a dados foi criado para ser a interface com o XML. Ele podia ler arquivos XML para popular seus objetos ou causar a extrusão do XML sob demanda para passar os dados e o esquema para outra camada. O nome fazia sentido. No entanto, a Microsoft decidiu que os desenvolvedores ficariam confusos e zangados se ela criasse mais uma interface de acesso a dados e, portanto, ela foi chamada de "ADO.NET". Certamente, o ADOc e o ADO.NET fazem a mesma coisa nos níveis mais altos. No entanto, a maneira como fazem isso por trás dos bastidores é muito diferente e (em minha opinião) muito melhor (na maior parte).

Quando o ADO.NET foi fornecido pela primeira vez, ele não tinha muitos dos recursos fundamentais que agora têm suporte total no ADOc evoluído. Esses recursos incluem atualizações em lotes, operações assíncronas, cursores do lado do servidor, geração de comandos de ação em tempo de execução e muito mais. É possível argumentar que o ADO.NET foi criado para uso com o ASP.NET, não necessariamente para aplicativos cliente/servidor, mas a Microsoft acredita que DataSets desconectados podem ajudar aplicativos cliente/servidor a serem mais eficientes e acabar com sua dependência de designs difíceis de dimensionar que dependem do gerenciamento de estado do lado do servidor. Por causa dessa filosofia, o ADO.NET não inclui suporte para cursores do lado do servidor. A nova abordagem era focalizar em um armazenamento de dados "desconectado" do lado do cliente que pudesse ser facilmente transferido e serializado para XML sob demanda para passar para outras camadas. Isso também funcionava bem para a nova iniciativa SOA (Service Oriented Architecture) da Microsoft de serviços da Web em XML. Observe que o XML usado para transferir um conjunto de registros do ADOc não é compatível com o formato XML esperado pelo ADO.NET. (Consulte Much ADO About Data: Doing the Impossible (Again), em inglês.) A Microsoft também percebeu que era melhor permitir que os desenvolvedores criassem seus próprios comandos de ação SQL (UPDATE, INSERT, DELETE) ou deixassem que os assistentes os criassem, em vez de contar com o código do método Update do ADOc controlado por propriedades que normalmente gerava erros ao tentar descobrir como fazer alterações em um conjunto de registros. Sim, eles também implementaram o CommandBuilder para criar comandos de ação automaticamente em cenários simples, mas, como eu descrevo em meu artigo sobre esse método, não acredito que você queira seguir esse caminho. (Consulte Weaning Developers from the CommandBuilder, em inglês.) Certamente, existem meios de contornar muitos desses problemas, mas esse esforço extra pode desencorajar ainda mais os desenvolvedores de migrarem ou tornar o processo ainda mais difícil.

Lidando com os problemas

Por outro lado, a Microsoft tratou diretamente do problema relacionado ao OSFA permitindo que os desenvolvedores gravassem em interfaces gerenciadas. Isto é, o ADO.NET expõe um provedor de dados do .NET especificamente para o Microsoft SQL Server (SqlClient) entre outros, incluindo o Oracle e o DB2. Isso significava que os engenheiros do provedor podiam usar todos os recursos de seu DBMS e comunicar-se com ele nos níveis mais baixos. Pela primeira vez desde a DBLibrary, o ADO.NET pôde interagir com o SQL Server usando o TDS (Tabular Data Stream), seu protocolo de nível baixo. Isso significava que o provedor do SqlClient podia acessar qualquer um dos recursos e nuanças do SQL Server para que os aplicativos pudessem fazer melhor uso de sua capacidade. Como as interfaces nativas eram semelhantes às interfaces OSFA do .NET implementadas pelos provedores de dados do .NET, OleDb e Odbc, os desenvolvedores não têm problemas para fazer a transição do código de um DBMS para outro.

O ADO.NET também expôs outro recurso do acesso direto da DBLibrary ao fluxo de dados retornado pela interface de dados de nível baixo. Implementada como um DataReader, essa interface conectada e somente de encaminhamento de uma linha por vez vincula seu código aos dados de entrada retornados por uma consulta. Todos os métodos no ADO.NET usam o DataReader diretamente ou nos bastidores para buscar conjuntos de resultados. Isso significa que seus aplicativos podem buscar dados mais rapidamente e ter mais controle sobre o processo.

Migrando habilidades de desenvolvimento do ADO Clássico

Em muitos casos, a lógica de acesso a dados na maioria dos aplicativos pode ser segmentada em várias partes:

  • Conexão: envolve a criação de uma seqüência de caracteres de conexão, em alguns casos integrando credenciais fornecidas pelo usuário e estabelecendo uma conexão just-in-time ou pela duração da operação.

  • Gerenciamento da consulta: isso significava a criação de uma seqüência de caracteres de consulta e a integração de parâmetros fornecidos pelo usuário. Abrange também o gerenciamento de transações.

  • Execução da consulta: inclui escolher um método de execução apropriado que corresponda aos conjuntos de resultados retornados. Algumas vezes, isso significa usar métodos que aceitam um conjunto de linhas, escalar ou fluxo ou simplesmente executar um comando de ação.

  • Gerenciamento dos conjuntos de resultados: essas rotinas armazenam e processam conjuntos de linhas, parâmetros retornados ou ligam os resultados a controles. Essas rotinas também podem gerenciar "relações" entre os conjuntos de linhas retornados, como ao trabalhar com dados hierárquicos. Em alguns designs, essas rotinas navegam pelos cursores do lado do cliente ou do servidor bem como classificam, filtram e localizam linhas.

  • Gerenciamento de alterações: quando os dados são alterados, essas rotinas movem os dados de fontes estáticas ou controles ligados para estruturas de dados do ADO que gerenciam atualizações, inserções e exclusões. Essas rotinas também gerenciam colisões simultâneas, operações em lotes e transações.

  • Gerenciamento de exceções: todas essas rotinas têm identificadores de exceção que tratam dos problemas que geralmente ocorrem conforme a conexão é feita, a consulta é preparada e executada e os dados são postados no servidor.

Os desenvolvedores do ADO descobrirão que o código em ADO.NET pode ser segmentado e codificado de maneiras semelhantes. No entanto, existem diferenças em cada parte que podem ser um pouco intimidantes à primeira vista, mas que se consideradas individualmente podem ser tratadas de maneira bastante fácil. Não, o assistente de conversão do Visual Basic 6.0 não converterá código em ADOc em ADO.NET. Isso é simplesmente impossível, dadas as diferenças de abordagem do ADO.NET. Por exemplo, se você usou a sintaxe SHAPE no ADOc para gerenciar hierarquias, descobrirá que o .NET Framework não oferece suporte a SHAPE, mas oferece suporte ao gerenciamento de vários conjuntos de linhas relacionados usando a classe DataSet que pode conter vários objetos DataTable, cada um contendo um conjunto de linhas independente.

Cada um dos provedores de dados do .NET é responsável por implementar seu próprio tipo de classes do ADO.NET. Todos eles oferecem suporte a um conjunto "principal" de operações usando (aproximadamente) as mesmas propriedades e configurações. É claro que cada um oferece suporte à sua própria variação do SQL e configurações de ConnectionString. Por exemplo, o provedor do SqlClient (usado para o Microsoft SQL Server) implementa um SqlConnection, SqlCommand, SqlDataAdapter e SqlDataReader, enquanto o provedor do OleDb oferece suporte ao OleDbConnection, OleDbCommand, etc. Eu faço referência a esses objetos por sua função em meus manuais, por exemplo, o SQLCommand é chamado de classe "Command".

A classe Connection (SqlConnection) do ADO.NET é semelhante ao objeto Connection do ADOc, mas ela aceita um ConnectionString diferente (embora familiar). Ela não pode ser aberta de maneira assíncrona, mas pode ser gerenciada automaticamente pelo DataAdapter quando você executa os métodos Fill e Update. Não é possível executar o SQL diretamente contra o objeto Connection no ADO.NET. Será necessário criar um Command para isso. Você também pode metamorfosear seus identificadores de erros de conexão para esperar o mesmo tipo de problemas ocorridos com as tentativas de conexão do ADOc. Observe que o ADOc usa quase que o mesmo mecanismo de pool de conexão que o ADO.NET, mas com o ADO.NET você pode gerenciar as opções e o estado de pool muito mais facilmente.

A classe Command do ADO.NET é semelhante ao objeto Command do ADOc, mas nesse caso você precisa criar um objeto Command para executar o SQL ou um procedimento armazenado. Os métodos expostos no objeto Command do ADO.NET são realmente muito diferentes. Ao contrário do ADOc, você tem acesso a uma nova interface de nível baixo, o DataReader (SqlDataReader), que expõe um fluxo de dados não processados de alta velocidade para retornar dados da consulta. A classe Command oferece suporte a uma coleção Parameters que é semelhante à usada no ADOc. Lembre-se de que a marcação de parâmetros do SQL é diferente no ADO.NET.

Você também descobrirá que o DataTable do ADO.NET é basicamente equivalente ao conjunto de registros do ADOc. Embora ele não seja gerenciado como um "cursor", você descobrirá que ele armazena e gerencia o conjunto de linhas retornado eficientemente. Navegar para uma linha específica é tão fácil quanto trabalhar com uma matriz. Você também pode gerenciar vários conjuntos de linhas de uma vez a partir de uma variedade de fontes de dados usando o DataSet. Essa é uma classe usada para gerenciar um ou muitos objetos DataTable e os conjuntos de linhas que eles contêm. Você pode codificar relações entre esses conjuntos de linhas (mesmo quando eles são provenientes de fontes díspares) e navegar, filtrar e pesquisar facilmente com base nas relações pai-filho especificadas por você.

A ligação de dados também foi alterada. Sem entrar na ladainha dos problemas relacionados à ligação de dados do Visual Basic 6.0, basta dizer que você pode fazer a ligação mais facilmente com conjuntos de linhas usando código de arrastar e soltar gerado ou configurando vinculações de ligação de dados em seu próprio código. O ADO.NET 2.0 refina ainda mais o paradigma da ligação de dados para tornar o processo ainda mais fácil.

Tratar do conjunto de dados do ADOc é bastante dispendioso, pois todas as colunas são retornadas como Variant. Como o ADO.NET pode usar DataTables e DataSets com rigidez de tipos, você descobrirá que é muito mais fácil abordar os objetos. Isso significa que os dados são armazenados e gerenciados em seu tipo nativo; um inteiro é armazenado como um inteiro e uma seqüência de caracteres é armazenada como uma seqüência de caracteres. Você também pode observar que as operações com rigidez de tipos são ordens de magnitude mais rapidamente. Também encorajamos que você use as opções "Option Strict On" e "Option Explicit On" no ambiente de desenvolvimento. Embora isso possa indicar que o código precisa forçar variáveis explicitamente (convertendo os tipos em código), o resultado será código mais estável que não apresentará falhas (como sempre) quando dados inesperados forem recebidos.

Para tornar as atualizações de tabelas mais simples, o DataAdapter do ADO.NET é padronizado pelo DOW (Data Object Wizard) do Visual Basic 6.0. Essa classe permite definir suas próprias instruções UPDATE, INSERT e DELETE do SQL, sejam elas uma consulta ad hoc do SQL ou um procedimento armazenado. Isso torna o ADO.NET muito mais leve, mas coloca a responsabilidade por esses comandos em seu código, e o ADO.NET não tenta mais gerar esses comandos em tempo de execução como o ADOc. Como você verá, o ADO.NET 2.0 reintroduz atualizações em lotes e também operações assíncronas para melhorar o desempenho.

Como com o ADOc, o tratamento de exceções representa uma grande parte do design do ADO.NET. Felizmente, o .NET Framework oferece suporte ao gerenciamento de exceções por tentativa e erro, que é muito mais poderoso e flexível do que as rotinas "Em erro" tradicionais do Visual Basic 6.0 com as quais você já deve estar habituado. Essa abordagem permite filtrar essas exceções centradas em dados específicas daquelas provocadas por outros problemas. Isso facilita a criação de identificadores de exceção e torna seus aplicativos menos propensos a falhas inesperadas.

Novidades do ADO.NET 2.0

A última versão do ADO.NET 2.0 preenche algumas das lacunas deixadas para trás quando você migra do ADOc e implementa vários recursos que nunca vimos antes. Muitas dessas inovações permitem criar código mais seguro, mais robusto (e mais rápido), mas principalmente aplicativos do Windows Forms (cliente/servidor). Essas atualizações incluem:

  • Nenhuma dependência do MDAC. Enquanto as versões anteriores do ADO.NET sempre requeriam uma atualização para a pilha do MDAC (que inclui as DLLs necessárias para executar aplicativos do ADOc), o ADO.NET 2.0 elimina essa dependência ao usar o SqlClient. Para provedores de dados OleDb e Odbc do .NET, versões mais antigas do MDAC (2.6 - 2.9) podem ser suficientes. Isso significa que a instalação de um aplicativo .NET é menos nociva, pois ela não perturbará os aplicativos ADOc existentes.

  • Operações assíncronas. Enquanto o ADO.NET 2.0 não pode abrir uma conexão de forma assíncrona como o ADOc, ele pode executar comandos do DataReader de forma assíncrona. Isso significa que você pode escrever código que entretenha o usuário com uma barra de progresso ou execute outro trabalho no segmento de seu aplicativo enquanto a consulta é executada (e retorna eventos de status conforme ele progride).

  • MARS (Multiple Active Result Sets). Nunca foi possível usar uma conexão para mais de uma operação; não até o ADO 2.0. O MARS pode oferecer suporte a várias operações na mesma conexão. Isso significa que você não precisa abrir tantas conexões ao ler e atualizar linhas ao mesmo tempo. Naturalmente, isso supõe que o provedor de dados do .NET e o DBMS de destino ofereçam suporte a esse recurso.

  • Processamento em lotes. O ADOc oferecia suporte à habilidade de enviar vários comandos de ação ao servidor em uma única viagem de ida e volta. Esse recurso foi reimplementado no ADO.NET 2.0. Colocando as operações do método Update em lotes, seu aplicativo pode fazer alterações muito mais rapidamente com menos viagens de ida e volta (dispendiosas) para o servidor.

  • Suporte de BCP. Ao mover dados de fontes de dados externas ou geradas, é importante usar o BCP (utilitário de cópia em massa) em vez de métodos convencionais do ADO.NET. O ADO.NET 2.0 agora inclui uma classe BCP para permitir acesso direto a essa funcionalidade de carregamento de dados de alta velocidade. Essa abordagem pode significar que transferências de dados em massa podem ser feitas em uma fração do tempo requerido pelos métodos convencionais do ADO.

  • Exposição de um DataSet como DataReader. Para facilitar a exposição de dados de camada para camada, você agora pode criar um DataSet (ou DataTable) e passar esses dados como um DataReader para outra camada. Também é possível carregar um DataTable diretamente de um DataReader.

  • Serialização de DataSet. Em versões anteriores, você podia usar a arquitetura de comunicação remota para passar DataSets entre camadas, mas os dados eram passados como XML. No ADO.NET 2.0 você pode serializar DataSets como binários. Isso significa desempenho muito (muito) mais rápido entre camadas, mas usa um formato proprietário da Microsoft para transportar os dados. Outra opção (SchemaSerializationMode=TypedDataSets) retira o esquema do fluxo de dados, reduzindo o volume de dados movimentado enquanto ainda permite cenários entre plataformas.

  • Suporte ao Yukon. Pela primeira vez, o ADO.NET 2.0 oferece suporte a tipos de dados nativos do SQL Server 2000 (e talvez) inclui suporte para tipos definidos pelo usuário baseados em CLR. Esses tipos incluem varchar(max), nvarchar(max), varbinary(max) e os novos tipos XML.

  • Nova classe base comum. Para facilitar a criação de aplicativos genéricos, o ADO.NET 2.0 expõe uma classe base DB*. Por exemplo, DbConnection, DbCommand e DbDataAdapter são expostos. Essas classes ainda requerem que a sintaxe SQL específica do provedor seja usada, mas elas podem possibilitar a criação de um único aplicativo que possa acessar várias fontes de dados diferentes.

  • Enumeração do servidor e do provedor. Essas novas classes permitem descobrir quais provedores de dados do .NET estão disponíveis e quais servidores e instâncias são visíveis a partir do aplicativo. Elas serão muito úteis durante a criação de ferramentas para gerenciar, iniciar/parar/pausar ou simplesmente determinar o status do servidor. Observe que o SQL Server agora expõe o SMO, além do SQL-DMO, para gerenciar instâncias do SQL Server.

  • Novos contadores. O provedor do SqlClient expôs vários contadores em versões anteriores do .NET, mas eles não eram particularmente confiáveis. Esses novos contadores prometem ser mais precisos e incluem a capacidade de determinar o estado do mecanismo do pool de conexão.

  • Gerenciamento do pool de conexão. Enquanto as versões anteriores permitiam que você escolhesse as opções do pool de conexão, o ADO.NET 2.0 permite limpar o pool ou todos os pools e executar outras funções para gerenciar o comportamento dos pools. O mecanismo do pool de conexão também foi melhorado para ajudar a detectar um pool inativo, que esteja conectado a um servidor não disponível.

Integração com o Whidbey

O ADO foi integrado ao Visual Basic e ao Visual Studio por algum tempo. No entanto, desta vez, a equipe do Visual Studio 2005 foi um pouco além em relação ao nível de integração. Embora não haja assistentes para criar o conhecido DataAdapter, existem técnicas de arrastar e soltar que geram várias estruturas de dados novas e conhecidas com rigidez de tipos. Lembre-se de que essas ferramentas são mais interessantes quando você deseja que a interface do RAD gere código para você, principalmente em casos simples. A Microsoft afirma que o suporte ao desenvolvimento de n camadas também exigiu muito trabalho. Você pode criar aplicativos que criam DataSets no mesmo assembly ou acessar datasets em assemblies referenciados, bem como seus próprios objetos em assemblies referenciados. Quando seus designs se tornam mais sofisticados, essas mesmas ferramentas podem expor objetos comerciais da camada intermediária que você mesmo gera. A discussão dessa integração está além do escopo deste artigo, mas ela será coberta no manual.

Quais são as alternativas?

Como com qualquer solução de software, existem várias maneiras alternativas de criar uma solução, e alguém sempre aponta dúzias de variações em cada ponto depois de terminado o trabalho. É claro, existem as compensações de cada abordagem. Neste caso, você irá se concentrar nos problemas da interface de acesso a dados e deixar as tarefas de conversão restantes para outros. Certamente, seu código de acesso a dados pode não ser tão fácil de isolar. Enquanto a maioria dos gurus da indústria e eu tenhamos falado sobre designs de três camadas (ou de n camadas) por umas duas décadas, nem todo mundo seguiu nosso conselho. Se você tiver criado um aplicativo com um conjunto independente de objetos de camada intermediária que manipulam dados, a tarefa de converter esses objetos para oferecer suporte ao ADO.NET será bastante óbvia. No entanto, se o seu código tiver uma aparência emaranhada, como o código que eu tenho analisado ao longo dos anos, você terá uma tarefa difícil ao extrair as rotinas do ADOc da malha de seu aplicativo sem que ele desmorone; será como tentar encontrar uma agulha em um palheiro. Vamos dar uma olhada nas abordagens alternativas; uma delas deve ser apropriada para você e suas habilidades.

  • Deixe que o assistente para importação de projetos do Visual Basic 6.0 converta seu projeto em um projeto do ADO.NET. Dizem que o novo assistente de conversão do Visual Studio 2005 está mais inteligente do que nunca, mas ele ainda não converte código em ADOc em ADO.NET. Embora isso possa levar algum tempo para projetos maiores e mais complexos, para projetos mais simples, a conversão deve ser bastante tranqüila. Depois da conversão, o que você obtém é seu código em ADOc metamorfoseado e empacotado em uma camada de interoperabilidade do COM, para que ele seja compilado no novo projeto do Visual Basic .NET, implantado (com a versão registrada do MDAC) e executado no sistema de destino. Isso também significa que você precisará tomar cuidado com as técnicas de codificação que eu discuto no artigo que escrevi no ano passado, nesta mesma época. Existem algumas técnicas de ligação tardias que não são muito bem metamorfoseadas.

  • Outra abordagem viável é visitar cada seção do código em ADOc e dividi-lo logicamente. Verifique se a tarefa pode ser feita com um DataSet desconectado ou simplesmente use um DataReader para retornar linhas. Isso é semelhante a um conjunto de registros do tipo "extintor de incêndio" padrão. Nesse caso, a conversão para o ADO.NET é um processo claro e direto. Quando você está lidando com cursores do lado do servidor (especialmente populares com aplicativos cliente/servidor), você precisa decidir sobre a estratégia que faz a reengenharia do código para usar um DataSet desconectado ou considerar o gerenciamento de uma classe de cursor do lado do servidor feita em casa usando operadores ANSI CURSOR. Vimos isso em muitos casos; a necessidade de cursores do lado do servidor pode ser eliminada com algumas poucas alterações no design. No entanto, talvez isso não seja possível; portanto, olhe antes de saltar.

  • Uma terceira abordagem é especialmente útil quando você isola seu código em ADOc em componentes de camada intermediária. Nesse caso, você pode substituir o código em ADOc "simplesmente" criando versões do ADO.NET dos componentes que retornam estruturas semelhantes, assumindo que o consumidor do componente não retorne conjuntos de registros do ADOc para a(s) outra(s) camada(s). Se você estiver expondo uma classe de objeto comercial personalizada, as ferramentas do Visual Studio 2005 poderão facilitar em muito a metamorfose para um componente de acesso a dados baseado no ADO.NET.

Considerações principais

Antes de atacar um processo de conversão, é necessário considerar o ponto de partida e fazer a pergunta: "eu consigo ir daqui até lá atravessando águas profundas?" Considere estes fatores que poderão afetar o processo de conversão:

  • De qual tipo de arquitetura você está migrando? Se você estiver migrando da programação ASP, a abordagem do ASP.NET é muito mais poderosa e gerencia os objetos do ADO de maneira muito diferente. Você gostará da nova abordagem, embora ela agora trate da ligação de dados bidirecionais que não tinha suporte até este momento.

  • Qual é o seu nível de habilidade? Com qual linguagem de computação você se sente mais à vontade? Se você tiver feito uma quantidade considerável de codificação no Visual Basic 6.0 e tiver trabalhado com o Visual Basic .NET por algum tempo (como muitos já trabalharam), poderá achar mais fácil simplesmente portar seu código "logicamente". Isto é, metamorfosear as operações, não o próprio código. Você poderá usar a maioria de suas seqüências de caracteres de conexão e o SQL, desde que não espere usar cursores do lado do servidor. Se suas habilidades não estiverem tão atualizadas, você poderá achar mais fácil simplesmente tentar o assistente de migração do Visual Studio 2005 e trabalhar a partir daí. É por isso que a maioria dos cenários simples são convertidos muito facilmente.

  • Quanto seu código depende da funcionalidade do lado do servidor, como de conjuntos de chaves ou de cursores dinâmicos, ou ainda de rotinas que gerenciam o estado do lado do servidor, como tabelas #temp? Nesse caso, o processo de conversão será mais difícil, pois mesmo o mais novo ADO.NET 2.0 não oferece suporte diretamente a essa funcionalidade. No entanto, existe a alternativa de usar comandos ANSI CURSOR. (Consulte meu artigo sobre o uso de instruções ANSI CURSOR, em inglês).

  • Você está migrando do ADO Clássico (ADOc versões 1.0 a 2.6) ou do DAO, ODBC ou de alguma outra interface proprietária de acesso a dados? Migrar de uma versão mais recente do ADO não é tão difícil, pois muitos dos conceitos são semelhantes, não iguais, apenas semelhantes. Se você usar o assistente de migração do Visual Basic 6.0, a maior parte do código em ADOc poderá ser portada sem alterações. Sim, existem alguns problemas que mencionei em meu artigo anterior.

  • No entanto, mover do DAO, da API do ODBC ou de uma interface proprietária é outro assunto. Os assistentes automatizados podem não ser capazes de converter o código de maneira nenhuma e podem nem mesmo tentar. Nesse caso, recomendo que você reavalie seu mecanismo do DBMS. Se estiver usando o DAO, você estará usando o JET, e normalmente eu recomendo que os clientes mudem do JET para o SQL Express, pois ele é mais poderoso, estável e escalável. A Microsoft está no processo de substituir o JET em todos os lugares o mais rapidamente possível. Recomendo o mesmo para meus clientes e alunos.

  • Quais controles ligados você está usando? Embora alguns controles simples, como TextBox, ListBox e ComboBox, tenham caminhos de conversão bastante fáceis, o DataGrid não tem. Considere que o mecanismo de ligação do Visual Basic .NET foi radicalmente melhorado e diferente; portanto, você pode encontrar várias desconexões quando se tratar de controles ligados. Muitas propriedades não são iguais em controles equivalentes do .NET, e você encontrará vários métodos inexistentes também. Controles de terceiros normalmente são oferecidos em uma versão do .NET. Talvez você queira investigá-los antes de se aventurar demais. No que diz respeito a controles personalizados, o Visual Studio 2005 faz um trabalho melhor de metamorfose, mas não espere muito. Suspeito que haverá muitos problemas com essa melhoria bastante recente do assistente de conversão.

  • Você está pronto para escrever sua própria lógica SQL para comandos de ação? Lembre-se de que o ADO Clássico criou esse SQL para você em tempo de execução baseado em sua instrução SELECT. Por outro lado, o ADO.NET o encoraja a codificar esses comandos de ação por conta própria. Sim, mencionei antes que você pode usar o CommandBuilder, mas as limitações dele vão aparecer rapidamente. Acredito que você não vai achar que ele seja tão flexível quanto o método Update do ADO Clássico, principalmente se você considerar como a propriedade Update Criteria permitia que você alterasse o tipo de comandos de ação criados.

Conclusão

Sim, é possível metamorfosear códigos em ADO "Clássico" em ADO.NET. Isso é tão difícil de fazer quanto parece? Duvido. Desde que você entenda que o ADO.NET não é o ADOc, mas uma interface de acesso a dados totalmente nova (e melhor), você se sentirá mais à vontade com o processo de conversão. Não, nem todos os aplicativos são destinados ou indicados para conversão. Como eu disse anteriormente, se não estiver quebrado, não conserte. Espero que isso ajude. Se você precisar de mais ajuda, aqui estão dois manuais que podem ajudar a começar. De qualquer forma, espero que este artigo o ajude a começar.

Livros relacionados

ADO.NET and ADO Examples and Best Practices for VB Programmers (em inglês)

ADO.NET Examples and Best Practices for C# Programmers (em inglês)

1. Metamorfosear [De metamorfose+ear] V.t.d. T. d. e I. Mudar ou trocar a forma de, transformar, modificar, alterar.
(Aurélio Século XXI O Dicionário da Língua Portuguesa, Editora Nova Fronteira)