Compartilhar via


TN045: Suporte de MFC/Banco de Dados para Varchar/Varbinary Longo

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 nota descreve como recuperar e enviar os tipos de dados ODBC SQL_LONGVARCHAR e SQL_LONGVARBINARY usando as classes de banco de dados MFC.

Visão geral do suporte long varchar/varbinary

Os tipos de dados ODBC SQL_LONG_VARCHAR e SQL_LONGBINARY (conhecidos aqui como colunas de dados longas) podem conter grandes quantidades de dados. Há três maneiras de lidar com esses dados:

  • Associá-lo a um CString/CByteArray.

  • Associá-lo a um CLongBinary.

  • Não associe e recupere e envie o valor de dados longos manualmente, independentemente das classes de banco de dados.

Cada um dos três métodos tem vantagens e desvantagens.

Não há suporte para colunas de dados longas para parâmetros para uma consulta. Eles só têm suporte para outputColumns.

Associar uma coluna de dados longos a um CString/CByteArray

Vantagens:

Essa abordagem é simples de entender e você trabalha com classes familiares. A estrutura fornece CFormView suporte para CString .DDX_Text Você tem muitas funcionalidades gerais de cadeia de caracteres ou coleção com as CString classes e CByteArray pode controlar a quantidade de memória alocada localmente para manter o valor dos dados. A estrutura mantém uma cópia antiga de dados de campo durante Edit ou AddNew chamadas de função, e a estrutura pode detectar automaticamente as alterações nos dados para você.

Observação

Como CString foi projetado para trabalhar em dados de caractere e CByteArray para trabalhar em dados binários, é recomendável colocar os dados de caractere (SQL_LONGVARCHAR) CStringe os dados binários (SQL_LONGVARBINARY) em CByteArray.

As funções RFX para CString e CByteArray têm um argumento adicional que permite substituir o tamanho padrão da memória alocada para manter o valor recuperado para a coluna de dados. Observe o argumento nMaxLength nas seguintes declarações de função:

void AFXAPI RFX_Text(CFieldExchange* pFX,
    const char *szName,
    CString& value,
    int nMaxLength = 255,
    int nColumnType =
    SQL_VARCHAR);

void AFXAPI RFX_Binary(CFieldExchange* pFX,
    const char *szName,
    CByteArray& value,
    int nMaxLength = 255);

Se você recuperar uma coluna de dados longa em um CString ou CByteArray, a quantidade máxima retornada de dados será, por padrão, 255 bytes. Qualquer coisa além disso é ignorada. Nesse caso, a estrutura lançará a exceção AFX_SQL_ERROR_DATA_TRUNCATED. Felizmente, você pode aumentar explicitamente nMaxLength para valores maiores, até MAXINT.

Observação

O valor de nMaxLength é usado pelo MFC para definir o buffer local da SQLBindColumn função. Esse é o buffer local para armazenamento dos dados e não afeta realmente a quantidade de dados retornados pelo driver ODBC. RFX_Text e RFX_Binary faça apenas uma chamada usando SQLFetch para recuperar os dados do banco de dados de back-end. Cada driver ODBC tem uma limitação diferente na quantidade de dados que pode retornar em uma única busca. Esse limite pode ser muito menor do que o valor definido em nMaxLength, nesse caso, a exceção AFX_SQL_ERROR_DATA_TRUNCATED será gerada. Nessas circunstâncias, mude para usar RFX_LongBinary em vez de RFX_Text ou RFX_Binary para que todos os dados possam ser recuperados.

ClassWizard associará um SQL_LONGVARCHAR a um CStringou um SQL_LONGVARBINARY a um CByteArray para você. Se você quiser alocar mais de 255 bytes nos quais recupera sua coluna de dados longa, poderá fornecer um valor explícito para nMaxLength.

Quando uma coluna de dados longa é associada a um CString ou CByteArray, atualizar o campo funciona exatamente como quando está associado a um SQL_VARCHAR ou SQL_VARBINARY. Durante Edit, o valor dos dados é armazenado em cache e posteriormente comparado quando Update é chamado para detectar alterações no valor de dados e definir os valores Dirty e Null para a coluna adequadamente.

Associar uma coluna de dados longos a um CLongBinary

Se sua coluna de dados longa pode conter mais bytes MAXINT de dados, você provavelmente deve considerar recuperá-la em um CLongBinary.

Vantagens:

Isso recupera uma coluna de dados longa inteira, até a memória disponível.

As desvantagens:

Os dados são mantidos na memória. Essa abordagem também é proibitivamente cara para grandes quantidades de dados. Você deve chamar SetFieldDirty o membro de dados associado para garantir que o campo esteja incluído em uma Update operação.

Se você recuperar colunas de dados longas em um CLongBinary, as classes de banco de dados verificarão o tamanho total da coluna de dados longa e, em seguida, alocarão um HGLOBAL segmento de memória grande o suficiente para mantê-lo todo o valor de dados. Em seguida, as classes de banco de dados recuperam todo o valor de dados no alocado HGLOBAL.

Se a fonte de dados não puder retornar o tamanho esperado da coluna de dados longa, a estrutura gerará a exceção AFX_SQL_ERROR_SQL_NO_TOTAL. Se a tentativa de alocar a HGLOBAL falha, uma exceção de memória padrão será gerada.

ClassWizard associará um SQL_LONGVARCHAR ou SQL_LONGVARBINARY a um CLongBinary para você. Selecione CLongBinary como o Tipo de Variável na caixa de diálogo Adicionar Variável de Membro. ClassWizard adicionará uma RFX_LongBinary chamada à sua DoFieldExchange chamada e incrementará o número total de campos associados.

Para atualizar valores de coluna de dados longos, primeiro verifique se o alocado HGLOBAL é grande o suficiente para manter seus novos dados chamando ::GlobalSize no membro m_hData do CLongBinary. Se for muito pequeno, libere e HGLOBAL aloque um do tamanho apropriado. Em seguida, defina m_dwDataLength para refletir o novo tamanho.

Caso contrário, se m_dwDataLength for maior do que o tamanho dos dados que você está substituindo, você poderá liberar e realocar o HGLOBAL, ou deixá-lo alocado. Certifique-se de indicar o número de bytes realmente usados em m_dwDataLength.

Como a atualização de um CLongBinary funciona

Não é necessário entender como a atualização de um CLongBinary funciona, mas pode ser útil como um exemplo sobre como enviar valores de dados longos para uma fonte de dados, se você escolher este terceiro método, descrito abaixo.

Observação

Para que um CLongBinary campo seja incluído em uma atualização, você deve chamar SetFieldDirty explicitamente o campo. Se você fizer qualquer alteração em um campo, incluindo defini-lo nulo, você deverá chamar SetFieldDirty. Você também deve chamar SetFieldNull, com o segundo parâmetro sendo FALSE, para marcar o campo como tendo um valor.

Ao atualizar um CLongBinary campo, as classes de banco de dados usam o mecanismo de DATA_AT_EXEC do ODBC (consulte a documentação do ODBC sobre SQLSetPoso argumento rgbValue). Quando a estrutura prepara a instrução de inserção ou atualização, em vez de apontar para os HGLOBAL dados que contêm, o endereço do CLongBinary é definido como o valor da coluna e o indicador de comprimento definido como SQL_DATA_AT_EXEC. Posteriormente, quando a instrução de atualização for enviada à fonte de dados, SQLExecDirect retornará SQL_NEED_DATA. Isso alerta a estrutura de que o valor do parâmetro para esta coluna é, na verdade, o endereço de um CLongBinary. A estrutura chama SQLGetData uma vez com um buffer pequeno, esperando que o driver retorne o comprimento real dos dados. Se o driver retornar o comprimento real do objeto binário grande (o BLOB), o MFC realoca o espaço necessário para buscar o BLOB. Se a fonte de dados retornar SQL_NO_TOTAL, indicando que não pode determinar o tamanho do BLOB, o MFC criará blocos menores. O tamanho inicial padrão é 64K e os blocos subsequentes serão o dobro do tamanho; por exemplo, o segundo será 128K, o terceiro é 256 K e assim por diante. O tamanho inicial é configurável.

Não associação: recuperando/enviando dados diretamente do ODBC com SQLGetData

Com esse método, você ignora completamente as classes de banco de dados e lida com a coluna de dados longa por conta própria.

Vantagens:

Você pode armazenar dados em cache no disco, se necessário, ou decidir dinamicamente a quantidade de dados a serem recuperados.

As desvantagens:

Você não obtém o suporte ou AddNew a estrutura Edit e deve escrever o código por conta própria para executar a funcionalidade básica (Delete no entanto, não funciona, já que não é uma operação de nível de coluna).

Nesse caso, a coluna de dados longa deve estar na lista de seleção do conjunto de registros, mas não deve ser associada pela estrutura. Uma maneira de fazer isso é fornecer sua própria instrução SQL por meio GetDefaultSQL ou como o argumento lpszSQL à CRecordsetfunção e Open não associar a coluna extra a uma chamada de função RFX_. O ODBC requer que os campos não associados apareçam à direita dos campos associados, portanto, adicione sua coluna ou colunas não associadas ao final da lista de seleção.

Observação

Como sua coluna de dados longa não está associada à estrutura, as alterações nela não serão tratadas com CRecordset::Update chamadas. Você deve criar e enviar as instruções SQL INSERT e UPDATE necessárias por conta própria.

Consulte também

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