TN053: rotinas DFX personalizadas para classes de banco de dados DAO

Observação

O DAO é usado com bancos de dados do Access e tem suporte do Office 2013. O DAO 3.6 é a versão final e é considerado obsoleto. O ambiente e os assistentes do Visual C++ não dão suporte a DAO (embora as classes DAO estejam incluídas e você ainda possa usá-las). A Microsoft recomenda que você use modelos OLE DB ou ODBC e MFC para novos projetos. Use DAO apenas na manutenção de aplicativos existentes.

Esta nota técnica descreve o mecanismo DFX (troca de campo de registro DAO). Para ajudar a entender o que acontece nas rotinas DFX, a função DFX_Text será explicada detalhadamente como um exemplo. Como fonte adicional de informações para esta nota técnica, você pode examinar o código das outras funções DFX individuais. Provavelmente, você não precisará de uma rotina DFX personalizada com a frequência na qual precisaria de uma rotina de RFX personalizada (usada com classes de banco de dados ODBC).

Esta nota técnica contém:

Visão geral do DFX

O mecanismo DFX (troca de campo de registro DAO) é usado para simplificar o procedimento de recuperar e atualizar dados ao usar a classe CDaoRecordset. O processo é simplificado usando membros de dados da classe CDaoRecordset. Ao derivar de CDaoRecordset, você pode adicionar membros de dados à classe derivada que representa cada campo em uma tabela ou consulta. Esse mecanismo de "associação estática" é simples, mas pode não ser o método de busca/atualização de dados ideal para todos os aplicativos. O DFX recupera todos os campos associados sempre que o registro atual é alterado. Se você está desenvolvendo um aplicativo sensível ao desempenho que não requer a busca de todos os campos quando a moeda é alterada, a "associação dinâmica" por meio de CDaoRecordset::GetFieldValue e CDaoRecordset::SetFieldValue pode ser o método de acesso a dados ideal.

Observação

O DFX e a associação dinâmica não são mutuamente exclusivos, portanto, um uso híbrido da associação estática e dinâmica pode ser usado.

Exemplo 1 – Uso somente da troca de campo de registro DAO

(pressupõe CDaoRecordset – classe derivada CMySet já aberta)

// Add a new record to the customers table
myset.AddNew();

myset.m_strCustID = _T("MSFT");

myset.m_strCustName = _T("Microsoft");

myset.Update();

Exemplo 2 – Uso somente da associação dinâmica

(pressupõe o uso da classe CDaoRecordset, rs e já está aberto)

// Add a new record to the customers table
COleVariant  varFieldValue1 (_T("MSFT"),
    VT_BSTRT);

//Note: VT_BSTRT flags string type as ANSI,
    instead of UNICODE default
COleVariant  varFieldValue2  (_T("Microsoft"),
    VT_BSTRT);

rs.AddNew();

rs.SetFieldValue(_T("Customer_ID"),
    varFieldValue1);

rs.SetFieldValue(_T("Customer_Name"),
    varFieldValue2);

rs.Update();

Exemplo 3 – Uso de troca de campos de registro DAO e da associação dinâmica

(pressupõe a navegação de dados de funcionários com a classe derivada de CDaoRecordset emp)

// Get the employee's data so that it can be displayed
emp.MoveNext();

// If user wants to see employee's photograph,
// fetch it
COleVariant varPhoto;
if (bSeePicture)
    emp.GetFieldValue(_T("photo"),
    varPhoto);

// Display the data
PopUpEmployeeData(emp.m_strFirstName,
    emp.m_strLastName,
    varPhoto);

Como o DFX funciona

O mecanismo DFX funciona de forma maneira semelhante ao mecanismo RFX (troca de campo de registro) usado pelas classes ODBC do MFC. Os princípios de DFX e RFX são os mesmos, mas há inúmeras diferenças internas. O design das funções DFX foi feito de maneira que praticamente todo o código é compartilhado pelas rotinas DFX individuais. No nível mais alto, o DFX só faz algumas coisas.

  • O DFX constrói a cláusula SQL SELECT e a cláusula SQL PARAMETERS, se necessário.

  • O DFX constrói a estrutura de associação usada pela função GetRows do DAO (trataremos mais disso posteriormente).

  • O DFX gerencia o buffer de dados usado para detectar campos sujos (quando o buffer duplo está sendo usado)

  • O DFX gerencia as matrizes de status NULL e DIRTY e define valores, quando necessário, para atualizações.

No centro do mecanismo DFX está a função DoFieldExchange da classe derivada CDaoRecordset. Essa função envia chamadas para as funções DFX individuais de um tipo de operação apropriado. Antes de chamar DoFieldExchange, as funções MFC internas definem o tipo de operação. A lista a seguir mostra os vários tipos de operação e uma breve descrição.

Operação Descrição
AddToParameterList Compila a cláusula PARAMETERS
AddToSelectList Compila a cláusula SELECT
BindField Configura a estrutura de associação
BindParam Define valores de parâmetro
Fixup Define status NULL
AllocCache Aloca cache para a verificação suja
StoreField Salva o registro atual no cache
LoadField Restaura o cache para os valores membro
FreeCache Libera o cache
SetFieldNull Define o status do campo & value como NULL
MarkForAddNew Marca campos como sujos quando não são PSEUDO NULL
MarkForEdit Marca campos como sujos quando não correspondem ao cache
SetDirtyField Define os valores de campo marcados como sujos

Na próxima seção, cada operação será explicada com mais detalhes para DFX_Text.

O recurso mais importante a entender sobre o processo de troca de campo de registro DAO é que ele usa a função GetRows do objeto CDaoRecordset. A função GetRows DAO pode funcionar de várias maneiras. Esta nota técnica descreverá GetRows brevemente, pois ela está fora do escopo. A GetRows DAO pode funcionar de várias maneiras.

  • Ela pode buscar vários registros e vários campos de dados de uma vez. Isso permite um acesso a dados mais rápido, com a complicação de lidar com uma estrutura de dados grande e com os deslocamentos apropriados para cada campo e cada registro de dados na estrutura. O MFC não aproveita esse mecanismo de busca de vários registros.

  • Outra maneira como GetRows pode funcionar é permitir que os programadores especifiquem os endereços de associação para os dados recuperados de cada campo para um registro de dados.

  • O DAO também "retorna a chamada" para o chamador para colunas de comprimento variável, a fim de permitir que o chamador aloque a memória. Esse segundo recurso tem o benefício de minimizar o número de cópias de dados, bem como de permitir o armazenamento direto de dados em membros de uma classe (a classe derivada CDaoRecordset). Esse segundo mecanismo é o método usado pelo MFC para associar a membros de dados em classes derivadas CDaoRecordset.

O que sua rotina personalizada de DFX faz

É evidente nessa discussão que a operação mais importante implementada em qualquer função DFX deve ser a capacidade de configurar as estruturas de dados necessárias para chamar GetRows com êxito. Há várias outras operações a que uma função DFX também deve dar suporte, mas nenhuma tão importante ou complexa quanto se preparar corretamente para a chamada GetRows.

O uso do DFX é descrito na documentação online. Essencialmente, há dois requisitos. Primeiro, os membros devem ser adicionados à classe derivada CDaoRecordset para cada campo e parâmetro associado. Depois isso, CDaoRecordset::DoFieldExchange deve ser substituído. Observe que o tipo de dados do membro é importante. Ele deve corresponder aos dados do campo no banco de dados ou, pelo menos, ser conversível a esse tipo. Por exemplo, um campo numérico no banco de dados, como um inteiro longo, sempre pode ser convertido em texto e associado a um membro CString, mas um campo de texto em um banco de dados pode não necessariamente ser convertido em uma representação numérica, como um inteiro longo, e associado a um membro inteiro longo. O DAO e o mecanismo de banco de dados Jet da Microsoft são responsáveis pela conversão (em vez do MFC).

Detalhes de DFX_Text

Conforme mencionado anteriormente, a melhor maneira de explicar como o DFX funciona usar um exemplo. Para isso, abordar os detalhes internos de DFX_Text deve ajudar muito a fornecer pelo menos uma compreensão básica do DFX.

  • AddToParameterList

    Essa operação compila a cláusula SQL PARAMETERS ("Parameters <param name>, <param type> ... ;") exigida pelo Jet. Cada parâmetro é nomeado e tipado (conforme especificado na chamada RFX). Consulte a função CDaoFieldExchange::AppendParamType para ver os nomes dos tipos individuais. No caso de DFX_Text, o tipo usado é text.

  • AddToSelectList

    Compila a cláusula SQL SELECT. Isso é bastante simples, pois o nome de coluna especificado pela chamada DFX é apenas acrescentado ("SELECT <column name>, ...").

  • BindField

    A mais complexa das operações. Conforme mencionado anteriormente, é aqui que a estrutura de associação de DAO usada por GetRows é configurada. Como você pode ver com base no código em DFX_Text, os tipos de informações na estrutura incluem o tipo de DAO usado (DAO_CHAR ou DAO_WCHAR no caso de DFX_Text). Além disso, o tipo de associação usada também é configurado. Em uma seção anterior, GetRows foi descrita apenas brevemente, mas foi suficiente explicar que o tipo de associação usada pelo MFC sempre é a associação de endereço direta (DAOBINDING_DIRECT). Além disso, para a associação de colunas de comprimento variável (como DFX_Text), a associação de retorno de chamada é usada para que o MFC possa controlar a alocação de memória e especificar um endereço com o comprimento correto. Isso significa que o MFC sempre pode instruir ao DAO "onde" colocar os dados, permitindo assim a associação direta às variáveis de membro. O restante da estrutura de associação é preenchido com itens como o endereço da função de retorno de chamada de alocação de memória e o tipo de associação de coluna (associação por nome de coluna).

  • BindParam

    Essa é uma operação simples que chama SetParamValue com o valor do parâmetro especificado no membro de parâmetro.

  • Fixup

    Preenche o status NULL para cada campo.

  • SetFieldNull

    Essa operação apenas marca cada status de campo como NULL e define o valor da variável membro como PSEUDO_NULL.

  • SetDirtyField

    Chama SetFieldValue para cada campo marcado como sujo.

Todas as operações restantes só lidam com o uso do cache de dados. O cache de dados é um buffer extra dos dados no registro atual usado para deixar algumas coisas mais simples. Por exemplo, campos "sujos" podem ser detectados automaticamente. Conforme descrito na documentação online, ele pode ser desativado completamente ou no nível do campo. A implementação do buffer utiliza um mapa. Esse mapa é usado para corresponder dinamicamente cópias alocadas dos dados com o endereço do campo "associado" (ou o membro de dados derivado CDaoRecordset).

  • AllocCache

    Aloca dinamicamente o valor do campo armazenado em cache e o adiciona ao mapa.

  • FreeCache

    Exclui o valor do campo armazenado em cache e o remove do mapa.

  • StoreField

    Copia o valor do campo atual para o cache de dados.

  • LoadField

    Copia o valor armazenado em cache para membro do campo.

  • MarkForAddNew

    Verifica se o valor do campo atual não é NULL e o marca como sujo, se necessário.

  • MarkForEdit

    Compara o valor do campo atual com o cache de dados e o marca como sujo, se necessário.

Dica

Modele suas rotinas de DFX personalizadas com base nas rotinas de DFX existentes para tipos de dados padrão.

Confira também

Observações técnicas por número
Observações técnicas por categoria