TN045: supporto di MFC/database per Long Varchar/Varbinary
Nota
La seguente nota tecnica non è stata aggiornata da quando è stata inclusa per la prima volta nella documentazione online. Di conseguenza, alcune procedure e argomenti potrebbero essere non aggiornati o errati. Per le informazioni più recenti, è consigliabile cercare l'argomento di interesse nell'indice della documentazione online.
Questa nota descrive come recuperare e inviare i tipi di dati odbc SQL_LONGVARCHAR e SQL_LONGVARBINARY usando le classi di database MFC.
Panoramica del supporto di Long Varchar/Varbinary
I tipi di dati ODBC SQL_LONG_VARCHAR e SQL_LONGBINARY (definiti qui per quanto tempo le colonne di dati) possono contenere grandi quantità di dati. Esistono tre modi per gestire questi dati:
Associarlo a un oggetto
CString
/CByteArray
.Associarlo a un oggetto
CLongBinary
.Non associarlo affatto e recuperare e inviare manualmente il valore di dati lungo, indipendentemente dalle classi di database.
Ognuno dei tre metodi presenta vantaggi e svantaggi.
Le colonne di dati lunghe non sono supportate per i parametri di una query. Sono supportati solo per outputColumns.
Associazione di una colonna di dati long a CString/CByteArray
Vantaggi:
Questo approccio è semplice da comprendere e si lavora con classi familiari. Il framework fornisce CFormView
supporto per CString
con DDX_Text
. Sono disponibili numerose funzionalità generali di stringa o raccolta con le CString
classi e CByteArray
ed è possibile controllare la quantità di memoria allocata localmente per contenere il valore dei dati. Il framework gestisce una copia precedente dei dati dei campi durante Edit
o AddNew
chiamate di funzione e il framework può rilevare automaticamente le modifiche ai dati.
Nota
Poiché CString
è progettato per lavorare sui dati di tipo carattere e CByteArray
per lavorare sui dati binari, è consigliabile inserire i dati di tipo carattere (SQL_LONGVARCHAR) in CString
e i dati binari (SQL_LONGVARBINARY) in CByteArray
.
Le funzioni RFX per CString
e CByteArray
hanno un argomento aggiuntivo che consente di eseguire l'override delle dimensioni predefinite della memoria allocata per contenere il valore recuperato per la colonna di dati. Si noti l'argomento nMaxLength nelle dichiarazioni di funzione seguenti:
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 si recupera una colonna di dati lunga in un CString
oggetto o CByteArray
, la quantità massima di dati restituita è, per impostazione predefinita, di 255 byte. Tutto ciò che non va oltre questo viene ignorato. In questo caso, il framework genererà l'eccezione AFX_SQL_ERROR_DATA_TRUNCATED. Fortunatamente, è possibile aumentare in modo esplicito nMaxLength a valori maggiori, fino a MAXINT.
Nota
Il valore di nMaxLength viene usato da MFC per impostare il buffer locale della SQLBindColumn
funzione. Si tratta del buffer locale per l'archiviazione dei dati e non influisce effettivamente sulla quantità di dati restituiti dal driver ODBC. RFX_Text
e RFX_Binary
effettuano una sola chiamata usando SQLFetch
per recuperare i dati dal database back-end. Ogni driver ODBC presenta una limitazione diversa per la quantità di dati che possono restituire in un singolo recupero. Questo limite può essere molto inferiore al valore impostato in nMaxLength, nel qual caso verrà generata l'eccezione AFX_SQL_ERROR_DATA_TRUNCATED . In queste circostanze, passare all'uso RFX_LongBinary
invece di RFX_Text
o RFX_Binary
in modo che tutti i dati possano essere recuperati.
ClassWizard associa un SQL_LONGVARCHAR a un CString
oggetto o un SQL_LONGVARBINARY a un oggetto CByteArray
per l'utente. Se si desidera allocare più di 255 byte in cui si recupera la colonna di dati lunga, è possibile specificare un valore esplicito per nMaxLength.
Quando una colonna di dati lunga è associata a o CString
CByteArray
, l'aggiornamento del campo funziona esattamente come quando è associato a un SQL_VARCHAR o SQL_VARBINARY. Durante Edit
, il valore dei dati viene memorizzato nella cache e successivamente confrontato quando viene chiamato per Update
rilevare le modifiche apportate al valore dei dati e impostare i valori Dirty e Null per la colonna in modo appropriato.
Associazione di una colonna di dati long a un CLongBinary
Se la colonna di dati lunga può contenere più byte MAXINT di dati, è consigliabile recuperarla in un oggetto CLongBinary
.
Vantaggi:
In questo modo viene recuperata un'intera colonna di dati lunga, fino alla memoria disponibile.
Svantaggi:
I dati sono contenuti in memoria. Questo approccio è anche eccessivamente costoso per grandi quantità di dati. È necessario chiamare SetFieldDirty
il membro dati associato per assicurarsi che il campo sia incluso in un'operazione Update
.
Se si recuperano colonne di dati lunghe in un CLongBinary
, le classi di database verificheranno le dimensioni totali della colonna di dati lunga, quindi allocare un HGLOBAL
segmento di memoria sufficientemente grande da contenere l'intero valore di dati. Le classi di database recuperano quindi l'intero valore di dati nell'oggetto allocato HGLOBAL
.
Se l'origine dati non può restituire le dimensioni previste della colonna di dati lunga, il framework genererà l'eccezione AFX_SQL_ERROR_SQL_NO_TOTAL. Se il tentativo di allocare l'oggetto ha esito negativo, viene generata un'eccezione HGLOBAL
di memoria standard.
ClassWizard associa un SQL_LONGVARCHAR o SQL_LONGVARBINARY a un oggetto per l'utente CLongBinary
. Selezionare CLongBinary
come tipo di variabile nella finestra di dialogo Aggiungi variabile membro. ClassWizard aggiungerà quindi una RFX_LongBinary
chiamata alla DoFieldExchange
chiamata e incrementerà il numero totale di campi associati.
Per aggiornare i valori delle colonne di dati lunghe, assicurarsi prima di tutto che l'oggetto allocato HGLOBAL
sia sufficientemente grande da contenere i nuovi dati chiamando ::GlobalSize nel membro m_hData dell'oggetto CLongBinary
. Se è troppo piccolo, rilasciare HGLOBAL
e allocare una delle dimensioni appropriate. Impostare quindi m_dwDataLength per riflettere le nuove dimensioni.
In caso contrario, se m_dwDataLength è maggiore delle dimensioni dei dati che si sta sostituendo, è possibile liberare e riallocare o HGLOBAL
lasciarli allocati. Assicurarsi di indicare il numero di byte effettivamente utilizzati in m_dwDataLength.
Funzionamento dell'aggiornamento di un CLongBinary
Non è necessario comprendere il funzionamento di un CLongBinary
oggetto, ma può essere utile come esempio su come inviare valori di dati lunghi a un'origine dati, se si sceglie questo terzo metodo, descritto di seguito.
Nota
Affinché un CLongBinary
campo venga incluso in un aggiornamento, è necessario chiamare SetFieldDirty
in modo esplicito il campo. Se si apporta una modifica a un campo, inclusa l'impostazione null, è necessario chiamare SetFieldDirty
. È inoltre necessario chiamare SetFieldNull
, con il secondo parametro fal edizione Standard, per contrassegnare il campo come valore.
Quando si aggiorna un CLongBinary
campo, le classi di database usano il meccanismo di DATA_AT_EXEC ODBC (vedere la documentazione ODBC sull'argomento SQLSetPos
rgbValue). Quando il framework prepara l'istruzione insert o update, anziché puntare all'oggetto HGLOBAL
contenente i dati, l'indirizzo di CLongBinary
viene impostato come valore della colonna e l'indicatore di lunghezza impostato su SQL_DATA_AT_EXEC. Successivamente, quando l'istruzione update viene inviata all'origine dati, SQLExecDirect
restituirà SQL_Nedizione EnterpriseD_DATA. In questo modo il framework avvisa che il valore del parametro per questa colonna è effettivamente l'indirizzo di un oggetto CLongBinary
. Il framework chiama SQLGetData
una volta con un buffer piccolo, prevedendo che il driver restituisca la lunghezza effettiva dei dati. Se il driver restituisce la lunghezza effettiva dell'oggetto binario di grandi dimensioni (BLOB), MFC rialloca la quantità di spazio necessaria per recuperare il BLOB. Se l'origine dati restituisce SQL_NO_TOTAL, a indicare che non è in grado di determinare le dimensioni del BLOB, MFC creerà blocchi più piccoli. La dimensione iniziale predefinita è 64K e i blocchi successivi saranno raddoppiati; ad esempio, il secondo sarà 128K, il terzo è 256K e così via. Le dimensioni iniziali sono configurabili.
Not Binding: recupero/invio di dati direttamente da ODBC con SQLGetData
Con questo metodo è possibile ignorare completamente le classi di database e gestire manualmente la colonna di dati lunga.
Vantaggi:
È possibile memorizzare nella cache i dati su disco, se necessario, o decidere in modo dinamico la quantità di dati da recuperare.
Svantaggi:
Non si ottiene il supporto o AddNew
il framework Edit
ed è necessario scrivere il codice manualmente per eseguire funzionalità di base (Delete
funziona tuttavia, poiché non è un'operazione a livello di colonna).
In questo caso, la colonna di dati lunga deve trovarsi nell'elenco di selezione del recordset, ma non deve essere associata al framework. Un modo per eseguire questa operazione consiste nell'fornire un'istruzione SQL personalizzata tramite GetDefaultSQL
o come argomento lpszSQL alla CRecordset
funzione di Open
e non associare la colonna aggiuntiva a una chiamata di funzione RFX_. ODBC richiede che i campi non associati vengano visualizzati a destra dei campi associati, quindi aggiungere la colonna o le colonne non associate alla fine dell'elenco di selezione.
Nota
Poiché la colonna di dati lunga non è associata al framework, le modifiche apportate non verranno gestite con CRecordset::Update
le chiamate. È necessario creare e inviare manualmente le istruzioni SQL IN edizione Standard RT e UPDATE necessarie.