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
Exemplos de uso da troca de campos de registro DAO e da associação dinâmica
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 derivadasCDaoRecordset
.
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çãoCDaoFieldExchange::AppendParamType
para ver os nomes dos tipos individuais. No caso deDFX_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 emDFX_Text
, os tipos de informações na estrutura incluem o tipo de DAO usado (DAO_CHAR ou DAO_WCHAR no caso deDFX_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 (comoDFX_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