Condividi tramite


Recordset: associazione dinamica di colonne di dati (ODBC)

Le informazioni contenute in questo argomento sono valide per le classi ODBC MFC.

I recordset gestiscono l'associazione delle colonne di tabella specificate in fase di progettazione, tuttavia in alcuni casi è necessario associare colonne che erano sconosciute in fase di progettazione. In questo argomento si spiega:

Nota

Questo argomento si applica agli oggetti derivati da CRecordset in cui non è stato implementato il recupero di righe in blocco. Le tecniche descritte in genere non sono consigliate se si utilizza il prelievo di righe in blocco. Per ulteriori informazioni sul recupero delle righe in blocco, vedere Recordset: recupero di record in blocco (ODBC).

Quando è possibile associare colonne in modo dinamico

Nota

La procedura guidata ODBC MFC non è disponibile in Visual Studio 2019 e versioni più recenti. È possibile comunque creare manualmente un consumer.

Durante la fase di progettazione, la Creazione guidata dell'applicazione MFC o la Creazione guidata consumer ODBC MFC (da Aggiungi classe) genera le classi di recordset basandosi sulle tabelle e colonne note nell'origine dati. I database possono cambiare tra il momento in cui si esegue la progettazione e quello in cui l'applicazione usa le tabelle e le colonne in fase di esecuzione. Tu o un altro utente potreste aggiungere o eliminare una tabella, oppure aggiungere o eliminare colonne da una tabella da cui dipende il recordset dell'applicazione. Questo forse non rappresenta un problema per tutte le applicazioni di accesso ai dati. Tuttavia, in questi casi, com'è possibile gestire le modifiche dello schema del database, senza eseguire la riprogettazione e la ricompilazione? Lo scopo del presente argomento è rispondere a questa domanda.

In questo argomento viene descritto il caso più comune, in cui è possibile associare le colonne in modo dinamico: dopo aver iniziato con un recordset basato su uno schema di database noto, si vogliono gestire colonne aggiuntive in fase di esecuzione. L'argomento presuppone inoltre che le colonne aggiuntive corrispondano ai membri dati di campo CString (il caso più comune), anche se vengono forniti suggerimenti per gestire altri tipi di dati.

Con una piccola quantità di codice aggiuntivo, è possibile:

Il recordset contiene ancora i membri dati per le colonne che erano note in fase di progettazione. Inoltre, include una piccola quantità di codice aggiuntivo che determina in modo dinamico se sono state aggiunte nuove colonne alla tabella di destinazione e, in tal caso, associa le nuove colonne alla memoria allocata in modo dinamico (invece che ai membri dati del recordset).

In questo argomento non vengono illustrati altri casi di associazione dinamica, come le colonne o tabelle eliminate. In questi casi, è necessario usare le chiamate all'API ODBC in modo più diretto. Per ulteriori informazioni, vedere la Guida di riferimento per programmatori ODBC.

Come vincolare le colonne in modo dinamico

Per associare le colonne in modo dinamico, è necessario conoscere (o essere in grado di determinare) i nomi delle colonne aggiuntive. È anche necessario allocare memoria per i membri dati di campo aggiuntivi, specificarne i nomi e i tipi e specificare il numero di colonne da aggiungere.

Nella discussione seguente sono menzionati due diversi recordset. Il primo è il recordset principale, che seleziona i record dalla tabella di destinazione. Il secondo è un recordset di colonne speciale usato per ottenere informazioni sulle colonne nella tua tabella obiettivo.

Processo generale

A livello generale, è necessario procedere come segue:

  1. Costruisci l'oggetto recordset principale.

    Facoltativamente, passare un puntatore a un oggetto CDatabase aperto o specificare le informazioni di connessione per il recordset di colonna in un altro modo.

  2. Eseguire i passaggi per aggiungere le colonne in modo dinamico.

    Consultare la procedura descritta nella sezione Aggiunta delle colonne qui sotto.

  3. Aprire il recordset principale.

    Il recordset seleziona i record e usa il trasferimento di campi di record (RFX) per associare le colonne statiche (mappate ai membri dati di campo del recordset) e le colonne dinamiche (mappate alla memoria aggiuntiva allocata).

Aggiunta delle colonne

L'associazione dinamica di colonne aggiunte in fase di esecuzione richiede i passaggi seguenti:

  1. Determinare in fase di esecuzione quali sono le colonne nella tabella di destinazione. Estrarre da tali informazioni un elenco delle colonne che sono state aggiunte alla tabella dopo la progettazione della classe recordset.

    Un buon approccio consiste nell'usare una classe recordset di colonna progettata per eseguire query sull'origine dati in modo da ottenere le informazioni sulle colonne per la tabella di destinazione, ad esempio il nome e il tipo di dati della colonna.

  2. Fornire spazio di archiviazione per i nuovi membri dati. Poiché la classe recordset principale non dispone di membri dati di campo per le colonne sconosciute, è necessario specificare una posizione in cui archiviare i nomi, i valori dei risultati ed eventualmente le informazioni sul tipo di dati (se le colonne sono di tipi di dati diversi).

    Un approccio consiste nel compilare uno o più elenchi dinamici, uno per i nuovi nomi delle colonne, un altro per i valori dei risultati e un terzo per i tipi di dati (se necessario). Questi elenchi, in particolare l'elenco dei valori, forniscono le informazioni e lo spazio di archiviazione necessario per il binding. La figura seguente illustra la compilazione degli elenchi.

    Compilazione di elenchi di colonne da associare in modo dinamico.
    Compilazione degli elenchi di colonne da associare in modo dinamico

  3. Aggiungere una chiamata di funzione RFX alla funzione DoFieldExchange del recordset principale per ciascuna colonna aggiunta. Queste chiamate RFX eseguono il recupero di un record, comprese le colonne aggiuntive, e collegano le colonne ai membri dati del set di record o alla memoria fornita in modo dinamico.

    Un approccio consiste nell'aggiungere un ciclo alla funzione DoFieldExchange del recordset principale, per scorrere l'elenco delle nuove colonne e chiamare la funzione RFX appropriata per ogni colonna nell'elenco. Per ogni chiamata RFX, passare un nome di colonna dall'elenco dei nomi delle colonne e una posizione di archiviazione nel membro corrispondente dell'elenco dei valori dei risultati.

Elenchi di colonne

Nella tabella seguente sono illustrati i quattro elenchi con cui è necessario lavorare.

Elenco Descrizione
Current-Table-Columns (Elenco 1 nella figura) Un elenco delle colonne attualmente presenti nella tabella dell'origine dati. Questo elenco potrebbe corrispondere all'elenco delle colonne attualmente collegate nel recordset.
Bound-Recordset-Columns (Elenco 2 nella figura) Un elenco delle colonne associate nel recordset. Queste colonne contengono già istruzioni RFX nella funzione DoFieldExchange.
Colonne da associare in modo dinamico (Elenco 3 nella figura) Un elenco delle colonne presenti nella tabella ma non nel recordset. Queste sono le colonne da associare in modo dinamico.
Dynamic-Column-Values (Elenco 4 nella figura) Un elenco che contiene l'archiviazione per i valori recuperati dalle colonne associate in modo dinamico. Gli elementi di questo elenco corrispondono uno a uno a quelli di Columns-to-Bind-Dynamically.

Compilazione degli elenchi

Dopo aver definito una strategia generale, è possibile occuparsi dei dettagli. Le procedure descritte nella parte restante di questo argomento illustrano come compilare gli elenchi riportati nella sezione Elenchi di colonne. Le procedure illustrano gli aspetti seguenti:

Determinazione delle colonne di tabella non incluse nel recordset

Compilare un elenco (Bound-Recordset-Columns, come l'elenco 2 nella figura) che contiene un elenco delle colonne già associate nel recordset principale. Compilare quindi un elenco (Columns-to-Bind-Dynamically, derivato da Current-Table-Columns e Bound-Recordset-Columns) che contiene i nomi di colonna presenti nella tabella dell'origine dati, ma non nel recordset principale.

Per determinare i nomi delle colonne non presenti nel recordset (Columns-to-Bind-Dynamically)
  1. Compilare un elenco (Bound-Recordset-Columns) delle colonne già associate nel recordset principale.

    Un approccio consiste nella creazione di Bound-Recordset-Columns in fase di progettazione. È possibile esaminare visivamente le chiamate di funzione RFX nella funzione DoFieldExchange del recordset per ottenere tali nomi. Impostare quindi l'elenco come una matrice inizializzata con i nomi.

    Ad esempio, la figura mostra Bound-Recordset-Columns (elenco 2) con tre elementi. Nella Bound-Recordset-Columns manca la colonna Phone, come mostrato nella Current-Table-Columns (Lista 1).

  2. Confrontare Current-Table-Columns e Bound-Recordset-Columns per compilare un elenco (Colonne-da-Collegare-Dinamicamente) delle colonne che non sono già collegate nel set di record principale.

    Un approccio consiste nel fare un loop attraverso l'elenco di colonne della tabella al tempo di esecuzione (Current-Table-Columns) e l'elenco di colonne già associate nel recordset (Bound-Recordset-Columns) in parallelo. Inserire in Columns-to-Bind-Dynamically tutti i nomi contenuti in Current-Table-Columns che non sono presenti in Bound-Recordset-Columns.

    Ad esempio, la figura mostra Columns-to-Bind-Dynamically (Elenco 3) con un solo elemento: la colonna Phone presente in Current-Table-Columns (Elenco 1) ma non in Bound-Recordset-Columns (Elenco 2).

  3. Compilare un elenco Dynamic-Column-Values (come l'elenco 4 nella figura), in cui archiviare i valori dei dati corrispondenti a ogni nome di colonna archiviato nell'elenco delle colonne da associare in modo dinamico (Columns-to-Bind-Dynamically).

    Gli elementi di questo elenco svolgono il ruolo di campi dati membri nel nuovo recordset. Sono i percorsi di archiviazione a cui sono associate le colonne dinamiche. Per le descrizioni degli elenchi, vedere Elenchi di colonne.

Fornire spazio di archiviazione per le nuove colonne

Impostare quindi i percorsi di archiviazione per le colonne da associare in modo dinamico. L'idea è fornire un elemento di elenco in cui archiviare ogni valore della colonna. Questi percorsi di archiviazione sono paralleli alle variabili membro del recordset, in cui sono archiviate le colonne associate normalmente.

Per fornire l'archiviazione dinamica per le nuove colonne (Dynamic-Column-Values)

  1. Creare Dynamic-Column-Values, parallelamente a Columns-to-Bind-Dynamically, per contenere il valore dei dati in ciascuna colonna.

    Ad esempio, la figura mostra Dynamic-Column-Values (Elenco 4) con un elemento: un CString oggetto contenente il numero di telefono effettivo per il record corrente: "555-1212".

    Nel caso più comune, Dynamic-Column-Values dispone di elementi di tipo CString. Se si usano colonne con svariati tipi di dati, è necessario un elenco in grado di contenere elementi di diversi tipi.

Il risultato delle procedure precedenti è costituito da due elenchi principali: Columns-to-Bind-Dynamically contenente i nomi delle colonne e Dynamic-Column-Values contenenti i valori nelle colonne per il record corrente.

Suggerimento

Se le nuove colonne non sono tutte dello stesso tipo di dati, può essere utile un altro elenco parallelo contenente elementi che definiscono in qualche modo il tipo di ciascun elemento corrispondente nell'elenco delle colonne. È possibile usare i valori AFX_RFX_BOOL, AFX_RFX_BYTE e così via, se necessario. Queste costanti sono definite in AFXDB.H. Scegliere un tipo di elenco in base alla modalità di rappresentazione dei tipi di dati della colonna.

Aggiunta di chiamate RFX per associare le colonne

Infine, predisporre l'associazione dinamica inserendo chiamate RFX per le nuove colonne nella funzione DoFieldExchange.

Per aggiungere in modo dinamico le chiamate RFX per le nuove colonne
  1. Nella funzione membro DoFieldExchange del recordset principale aggiungere codice per scorrere in ciclo l'elenco delle nuove colonne (Columns-to-Bind-Dynamically). In ogni ciclo, estrarre da Columns-to-Bind-Dynamically un nome di colonna e da Dynamic-Column-Values un valore di risultato per la colonna. Passare questi elementi a una chiamata di funzione RFX appropriata per il tipo di dati della colonna. Per le descrizioni degli elenchi, vedere Elenchi di colonne.

Nel caso più comune, nelle chiamate di funzioni RFX_Text si estraggono dagli elenchi gli oggetti CString, come nelle righe di codice seguenti, in cui Columns-to-Bind-Dynamically è un oggetto CStringList denominato m_listName e Dynamic-Column-Values è un oggetto CStringList denominato m_listValue:

RFX_Text( pFX,
            m_listName.GetNext( posName ),
            m_listValue.GetNext( posValue ));

Per altre informazioni sulle funzioni RFX, vedere Macro e funzioni globali nelle informazioni di riferimento sulla libreria di classi.

Suggerimento

Se le nuove colonne sono di diversi tipi di dati, usare un'istruzione switch nel ciclo per chiamare la funzione RFX appropriata per ogni tipo.

Quando il framework chiama DoFieldExchange durante il processo Open per associare le colonne al recordset, le chiamate RFX per le colonne statiche associano tali colonne. Il ciclo chiama quindi ripetutamente le funzioni RFX per le colonne dinamiche.

Vedi anche

Recordset (ODBC)
Recordset: gestione di dati di grandi dimensioni (ODBC)