Partilhar via


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

Observação

O DAO é usado com bancos de dados do Access e é suportado pelo Office 2013. DAO 3.6 é a versão final, e é considerado obsoleto. O ambiente e os assistentes do Visual C++ não oferecem 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. Você só deve usar o DAO na manutenção de aplicativos existentes.

Esta nota técnica descreve o mecanismo de troca de campo de registro DAO (DFX). Para ajudar a entender o que está a acontecer nas rotinas de DFX, a função DFX_Text será explicada como exemplo em detalhes. Como fonte adicional de informações para esta nota técnica, você pode examinar o código para as outras funções DFX individuais. Você provavelmente não precisará de uma rotina DFX personalizada com tanta frequência quanto você pode precisar de uma rotina RFX personalizada (usada com classes de banco de dados ODBC).

Esta nota técnica contém:

Visão geral do DFX

O mecanismo de troca de campo de registro DAO (DFX) é usado para simplificar o procedimento de recuperação e atualização de dados ao usar a CDaoRecordset classe. O processo é simplificado usando membros de dados da CDaoRecordset classe. Derivando de CDaoRecordset, pode adicionar membros de dados à classe derivada que representa cada campo numa tabela ou consulta. Esse mecanismo de "vinculação estática" é simples, mas pode não ser o método de busca/atualização de dados preferido para todos os aplicativos. O DFX recupera todos os campos vinculados sempre que o registo atual é alterado. Se você estiver desenvolvendo um aplicativo sensível ao desempenho que não exija buscar todos os campos quando a moeda for alterada, a "vinculação dinâmica" via CDaoRecordset::GetFieldValue e CDaoRecordset::SetFieldValue pode ser o método de acesso a dados preferido.

Observação

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

Exemplo 1 — Uso apenas do DAO Record Field Exchange

(assume — 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 — Utilização apenas da ligação dinâmica

(assume-se o uso da CDaoRecordset classe, 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 do DAO Record Field Exchange e vinculação dinâmica

(pressupõe a navegação de dados de funcionários com CDaoRecordsetclasse empderivada)

// 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 funciona o DFX

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

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

  • DFX constrói a estrutura de ligação usada pela função do GetRows DAO (mais sobre isso mais tarde).

  • O DFX gerencia o buffer de dados usado para detetar campos sujos (se o buffer duplo estiver sendo usado)

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

No coração do mecanismo DFX está a CDaoRecordset função da DoFieldExchange classe derivada. Esta 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, defina o tipo de operação. A lista a seguir mostra os vários tipos de operação e uma breve descrição.

Funcionamento Descrição
AddToParameterList Constrói a cláusula PARAMETERS
AddToSelectList Constrói a cláusula SELECT
BindField Configura a estrutura de vinculação
BindParam Define valores de parâmetros
Fixup Atribui o estado NULL
AllocCache Aloca cache para verificação suja
StoreField Salva o registro atual no cache
LoadField Restaura o cache para valores de membro
FreeCache Libera a cache
SetFieldNull Define o status do campo e valor como NULL
MarkForAddNew Marca campos sujos, se não PSEUDO NULL
MarkForEdit Marca campos sujos se não corresponderem ao cache
SetDirtyField Define valores de campo marcados como sujos

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

Para entender o recurso mais importante do processo de troca de campo de registro DAO, é essencial saber que ele utiliza a função GetRows do objeto CDaoRecordset. A função DAO GetRows pode funcionar de várias maneiras. A presente nota técnica descreverá apenas sucintamente GetRows , uma vez que está fora do âmbito da presente nota técnica. DAO GetRows pode funcionar de várias maneiras.

  • Ele pode buscar vários registros e vários campos de dados ao mesmo tempo. Isto permite um acesso mais rápido aos dados, com a complicação de gerir uma grande estrutura de dados e os offsets apropriados para cada campo e para cada registo de dados na estrutura. MFC não tira partido deste mecanismo de busca de múltiplos registos.

  • Outra maneira GetRows de funcionar é permitir que os programadores especifiquem endereços vinculativos para os dados recuperados de cada campo para um registro de dados.

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

O que sua rotina DFX personalizada faz

É evidente a partir desta 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 GetRowscom êxito . Há uma série de outras operações que uma função DFX também deve suportar, mas nenhuma tão importante ou complexa quanto se preparar corretamente para a GetRows chamada.

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

Detalhes da DFX_Text

Como mencionado anteriormente, a melhor maneira de explicar como o DFX funciona é trabalhar através de um exemplo. Para este efeito, passar pelos aspectos internos do DFX_Text deve ser eficaz para ajudar a proporcionar pelo menos uma compreensão básica do DFX.

  • AddToParameterList

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

  • AddToSelectList

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

  • BindField

    A mais complexa das operações. Como mencionado anteriormente, é aqui que a estrutura de vinculação DAO usada por GetRows é configurada. Como você pode ver a partir do código nos DFX_Text tipos de informações na estrutura incluem o tipo DAO usado (DAO_CHAR ou DAO_WCHAR no caso de DFX_Text). Além disso, o tipo de vinculação usado também é configurado. Numa seção anterior, GetRows foi descrito apenas brevemente, mas foi suficiente para explicar que o tipo de vinculação usado pelo MFC é sempre a vinculação de endereço direto (DAOBINDING_DIRECT). Além disso, para a vinculação de colunas com comprimento variável (como DFX_Text), é utilizada a vinculação de retorno de chamada para que o MFC possa controlar a alocação de memória e especificar um endereço com o comprimento correto. O que isso significa é que o MFC sempre pode dizer ao DAO "onde" colocar os dados, permitindo assim a ligação direta às variáveis membros. O resto da estrutura de vinculação é preenchido com coisas como o endereço da função de retorno de chamada de alocação de memória e o tipo de vinculação de coluna (vinculação por nome de coluna).

  • BindParam

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

  • Fixup

    Preenche o status NULL para cada campo.

  • SetFieldNull

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

  • SetDirtyField

    Chamadas SetFieldValue para cada campo marcado sujo.

Todas as operações restantes lidam apenas com o uso do cache de dados. O cache de dados é um buffer extra dos dados no registro atual que é usado para tornar certas coisas mais simples. Por exemplo, os campos "sujos" podem ser detetados automaticamente. Conforme descrito na documentação on-line, ele pode ser desligado completamente ou no nível de campo. A implementação do buffer utiliza um mapa. Este mapa é utilizado para associar cópias dos dados, alocadas dinamicamente, ao endereço do campo "vinculado" (ou 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 o membro de campo.

  • MarkForAddNew

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

  • MarkForEdit

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

Sugestão

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

Ver também

Notas técnicas por número
Notas técnicas por categoria