Partilhar via


TN043: rotinas RFX

Observação

A nota técnica a seguir não foi atualizada desde que foi incluída pela primeira vez na documentação online. Como resultado, alguns procedimentos e tópicos podem estar desatualizados ou incorretos. Para obter as informações mais recentes, é recomendável que você pesquise o tópico de interesse no índice de documentação online.

Esta observação descreve a arquitetura RFX (Record Field Exchange). Ele também descreve como você escreve um procedimento RFX_.

Visão geral de Record Field Exchange

Todas as funções de campo de conjunto de registros são feitas com código C++. Não há recursos especiais ou macros mágicas. O coração do mecanismo é uma função virtual que deve ser substituída em cada classe de conjunto de registros derivada. Ela é sempre encontrada nesta forma:

void CMySet::DoFieldExchange(CFieldExchange* pFX)
{
    //{{AFX_FIELD_MAP(CMySet)
        <recordset exchange field type call>
        <recordset exchange function call>
    //}}AFX_FIELD_MAP
}

Os comentários AFX em formato especial permitem que o ClassWizard localize e edite o código nessa função. O código que não seja compatível com ClassWizard deve ser colocado fora dos comentários de formato especial.

No exemplo acima, <recordset_exchange_field_type_call> está na forma:

pFX->SetFieldType(CFieldExchange::outputColumn);

e <recordset_exchange_function_call> está na forma:

RFX_Custom(pFX, "Col2", m_Col2);

A maioria das funções RFX_ tem três argumentos, conforme mostrado acima, mas alguns (por exemplo, RFX_Text e RFX_Binary) têm argumentos opcionais adicionais.

Mais de um RFX_ pode ser incluído em cada função DoDataExchange.

Consulte 'afxdb.h' para obter uma lista de todas as rotinas de troca de campo de conjunto de registros fornecidas com MFC.

As chamadas de campo do conjunto de registros são uma maneira de registrar locais de memória (geralmente membros de dados) para armazenar dados de campo para uma classe CMySet.

Observações

As funções de campo do conjunto de registros são projetadas para funcionar somente com as classes CRecordset. Eles geralmente não são utilizáveis por nenhuma outra classe MFC.

Os valores iniciais dos dados são definidos no construtor C++ padrão, geralmente em um bloco com comentários //{{AFX_FIELD_INIT(CMylSet) e //}}AFX_FIELD_INIT.

Cada função RFX_ deve dar suporte a várias operações, desde o retorno do status sujo do campo até o arquivamento do campo em preparação para edição do campo.

Cada função que chama DoFieldExchange (por exemplo SetFieldNull, IsFieldDirty) faz sua própria inicialização em torno da chamada para DoFieldExchange.

Como funciona

Você não precisa entender o seguinte para usar a troca de campo de registro. No entanto, entender como isso funciona nos bastidores ajudará você a escrever seu próprio procedimento de troca.

A função de membro DoFieldExchange é muito parecida com a função de membro Serialize – ela é responsável por obter ou definir dados de/para um formulário externo (nesse caso, colunas do resultado de uma consulta ODBC) de/para dados de membro na classe. O parâmetro pFX é o contexto para fazer a troca de dados e é semelhante ao parâmetro CArchive para CObject::Serialize. O pFX (um objeto CFieldExchange) tem um indicador de operação, que é semelhante a, mas uma generalização do sinalizador de direção CArchive. Uma função RFX pode ter que dar suporte às seguintes operações:

  • BindParam – Indique onde o ODBC deve recuperar dados de parâmetro

  • BindFieldToColumn – Indique onde o ODBC deve recuperar/depositar dados de outputColumn

  • Fixup – Definir comprimentos CString/CByteArray, definir o bit de status NULL

  • MarkForAddNew – Marcar sujo se o valor tiver sido alterado desde a chamada AddNew

  • MarkForUpdate – Marcar sujo se o valor tiver sido alterado desde Editar chamada

  • Name – Anexar nomes de campo para campos marcados como sujos

  • NameValue – Acrescentar "<column name>=" para campos marcados como sujos

  • Value – Acrescentar "" seguido pelo separador, como ',' ou ' '

  • SetFieldDirty – Definir o campo de bit de status sujo (ou seja, alterado)

  • SetFieldNull – Definir o bit de status que indica o valor nulo para o campo

  • IsFieldDirty – Valor retornado do bit de status sujo

  • IsFieldNull – Valor retornado do bit de status nulo

  • IsFieldNullable – Retornar TRUE se o campo puder conter valores NULL

  • StoreField – Valor do campo de arquivamento

  • LoadField – Recarregar o valor do campo arquivado

  • GetFieldInfoValue – Retornar informações gerais em um campo

  • GetFieldInfoOrdinal – Retornar informações gerais em um campo

Extensões de usuário

Há várias maneiras de estender o mecanismo RFX padrão. Você pode

  • Adicionar novos tipos de dados. Por exemplo:

    CBookmark
    
  • Adicionar novos procedimentos de troca (RFX_).

    void AFXAPI RFX_Bigint(CFieldExchange* pFX,
        const char *szName,
        BIGINT& value);
    
  • Fazer com que a função de membro DoFieldExchange inclua condicionalmente chamadas RFX adicionais ou quaisquer outras instruções C++ válidas.

    while (posExtraFields != NULL)
    {
        RFX_Text(pFX,
        m_listName.GetNext(posExtraFields),
        m_listValue.GetNext(posExtraValues));
    }
    

Observação

Esse código não pode ser editado pelo ClassWizard e deve ser usado somente fora dos comentários de formato especial.

Escrevendo um RFX personalizado

Para escrever sua própria função RFX personalizada, é sugerido que você copie uma função RFX existente e modifique-a para suas próprias finalidades. Selecionar o RFX correto a ser copiado pode facilitar muito o trabalho. Algumas funções RFX têm algumas propriedades exclusivas que você deve levar em conta ao decidir qual copiar.

RFX_Long e RFX_Int: estas são as funções RFX mais simples. O valor dos dados não precisa de nenhuma interpretação especial, e o tamanho dos dados é fixo.

RFX_Single e RFX_Double: como RFX_Long e RFX_Int acima, essas funções são simples e podem usar amplamente a implementação padrão. Elas são armazenadas em dbflt.cpp em vez de dbrfx.cpp, no entanto, para habilitar o carregamento da biblioteca de pontos flutuantes do runtime somente quando elas são explicitamente referenciadas.

RFX_Text e : Essas duas funções pré-alocam um buffer estático para armazenar informações de cadeia de caracteres/binárias e RFX_Binarydevem registrar esses buffers com ODBC SQLBindCol em vez de registrar &valor. Por isso, essas duas funções têm muito código de caso especial.

RFX_Date: ODBC retorna informações de data e hora em sua própria estrutura de dados TIMESTAMP_STRUCT. Essa função aloca dinamicamente um TIMESTAMP_STRUCT como um "proxy" para enviar e receber dados de data/hora. Várias operações devem transferir as informações de data e hora entre o objeto C++ CTime e o proxy de TIMESTAMP_STRUCT. Isso complica consideravelmente essa função, mas é um bom exemplo de como usar um proxy para transferência de dados.

RFX_LongBinary: essa é a única função RFX da biblioteca de classes que não usa a associação de coluna para receber e enviar dados. Essa função ignora a operação BindFieldToColumn e, em vez disso, durante a operação Fixup, aloca o armazenamento para armazenar os dados de entrada SQL_LONGVARCHAR ou SQL_LONGVARBINARY e, em seguida, executa uma chamada SQLGetData para recuperar o valor no armazenamento alocado. Ao se preparar para enviar valores de dados de volta para a fonte de dados (como operações NameValue e Value), essa função usa a funcionalidade de DATA_AT_EXEC do ODBC. Consulte a Nota Técnica 45 para obter mais informações sobre como trabalhar com SQL_LONGVARBINARY e SQL_LONGVARCHARs.

Ao escrever sua própria função RFX_, você geralmente poderá usar CFieldExchange::Default para implementar uma determinada operação. Examine a implementação de Padrão para a operação em questão. Se ele executar a operação que você escreverá em sua função RFX_, você poderá delegar ao CFieldExchange::Default. Você pode ver exemplos de chamada de CFieldExchange::Default em dbrfx.cpp

É importante chamar IsFieldType no início da função RFX e retornar imediatamente se ela retornar FALSE. Esse mecanismo impede que as operações de parâmetro sejam executadas em outputColumns e vice-versa (como chamar BindParam em um outputColumn). Além disso, IsFieldType controla automaticamente a contagem de outputColumns (m_nFields) e params (m_nParams).

Confira também

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