TN043: RFX-Routinen
Hinweis
Der folgende technische Hinweis wurde seit dem ersten Erscheinen in der Onlinedokumentation nicht aktualisiert. Daher können einige Verfahren und Themen veraltet oder falsch sein. Um aktuelle Informationen zu erhalten, wird empfohlen, das gewünschte Thema im Index der Onlinedokumentation zu suchen.
In diesem Hinweis wird die Architektur des Datensatzfeldaustauschs (RECORD Field Exchange, RFX) beschrieben. Außerdem wird beschrieben, wie Sie eine RFX_ Prozedur schreiben.
Übersicht über Datensatzfeldaustausch
Alle Recordsetfeldfunktionen werden mit C++-Code ausgeführt. Es gibt keine speziellen Ressourcen oder magischen Makros. Das Herzstück des Mechanismus ist eine virtuelle Funktion, die in jeder abgeleiteten Recordsetklasse überschrieben werden muss. Sie wird immer in dieser Form gefunden:
void CMySet::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CMySet)
<recordset exchange field type call>
<recordset exchange function call>
//}}AFX_FIELD_MAP
}
Mit dem speziellen Format von AFX-Kommentaren kann ClassWizard den Code in dieser Funktion suchen und bearbeiten. Code, der nicht mit ClassWizard kompatibel ist, sollte außerhalb der Speziellen Formatkommentare platziert werden.
Im obigen Beispiel <befindet sich recordset_exchange_field_type_call> in der Form:
pFX->SetFieldType(CFieldExchange::outputColumn);
und <recordset_exchange_function_call> befindet sich in der Form:
RFX_Custom(pFX, "Col2", m_Col2);
Die meisten RFX_ Funktionen weisen drei Argumente auf, wie oben dargestellt, aber einige (z. B. RFX_Text
und RFX_Binary
) weisen zusätzliche optionale Argumente auf.
In jeder DoDataExchange
Funktion können mehrere RFX_ enthalten sein.
Eine Liste aller Recordsetfeldaustauschroutinen, die mit MFC bereitgestellt werden, finden Sie unter "afxdb.h".
Recordset-Feldaufrufe stellen eine Möglichkeit dar, Speicherspeicherorte (in der Regel Datenmember) zu registrieren, um Felddaten für eine CMySet
Klasse zu speichern.
Hinweise
Recordset-Feldfunktionen sind so konzipiert, dass sie nur mit den CRecordset
Klassen funktionieren. Sie können in der Regel nicht von anderen MFC-Klassen verwendet werden.
Anfangswerte von Daten werden im C++-Standardkonstruktor festgelegt, in der Regel in einem Block mit //{{AFX_FIELD_INIT(CMylSet)
und //}}AFX_FIELD_INIT
Kommentaren.
Jede RFX_-Funktion muss verschiedene Vorgänge unterstützen, von der Rückgabe des modifiziert Status des Felds bis hin zur Archivierung des Felds zur Bearbeitung des Felds.
Jede Funktion, die aufruft DoFieldExchange
(z. B SetFieldNull
. ), IsFieldDirty
führt eine eigene Initialisierung um den Aufruf durch DoFieldExchange
.
Funktionsweise
Sie müssen folgendes nicht verstehen, um den Datensatzfeldaustausch zu verwenden. Das Verständnis, wie dies im Hintergrund funktioniert, hilft Ihnen jedoch, Ihr eigenes Austauschverfahren zu schreiben.
Die DoFieldExchange
Memberfunktion ähnelt der Serialize
Memberfunktion – sie ist für das Abrufen oder Festlegen von Daten an/aus einem externen Formular (in diesem Fall Spalten aus dem Ergebnis einer ODBC-Abfrage) von/zu Memberdaten in der Klasse verantwortlich. Der pFX-Parameter ist der Kontext für den Datenaustausch und ähnelt dem CArchive-Parameter CObject::Serialize
. Der pFX (ein CFieldExchange
Objekt) weist einen Vorgangsindikator auf, der ähnlich ist, aber eine Generalisierung des CArchive-Richtungsflags . Eine RFX-Funktion muss möglicherweise die folgenden Vorgänge unterstützen:
BindParam
— Gibt an, wo ODBC Parameterdaten abrufen sollBindFieldToColumn
— Gibt an, wo ODBC-Ausgabedaten abrufen/ablegen müssen.Fixup
— Längen festlegenCString/CByteArray
, NULL-Statusbit festlegenMarkForAddNew
— Mark modifiziert if value has changed since AddNew callMarkForUpdate
— Mark modifiziert if value has changed since Edit callName
— Anfügen von Feldnamen für Felder, die als modifiziert markiert sindNameValue
— Fügen Sie "<Spaltenname>=" für Felder an, die modifiziertValue
— Fügen Sie "" gefolgt von Trennzeichen an, z. B. ',' oder 'SetFieldDirty
— Festlegen des Statusbits modifiziert (d. h. geändert) feldSetFieldNull
— Festlegen des Statusbits, das den Nullwert für das Feld angibtIsFieldDirty
— Rückgabewert modifiziert StatusbitsIsFieldNull
— Rückgabewert des NullstatusbitsIsFieldNullable
— True zurückgeben, wenn das Feld NULL-Werte enthalten kannStoreField
— ArchivfeldwertLoadField
— Wert des archivierten Felds erneut ladenGetFieldInfoValue
— Allgemeine Informationen zu einem Feld zurückgebenGetFieldInfoOrdinal
— Allgemeine Informationen zu einem Feld zurückgeben
Benutzererweiterungen
Es gibt mehrere Möglichkeiten zum Erweitern des standardmäßigen RFX-Mechanismus. Sie können
Fügen Sie neue Datentypen hinzu. Beispiel:
CBookmark
Hinzufügen neuer Austauschprozeduren (RFX_).
void AFXAPI RFX_Bigint(CFieldExchange* pFX, const char *szName, BIGINT& value);
Weisen Sie die
DoFieldExchange
Memberfunktion bedingt zusätzliche RFX-Aufrufe oder andere gültige C++-Anweisungen auf.while (posExtraFields != NULL) { RFX_Text(pFX, m_listName.GetNext(posExtraFields), m_listValue.GetNext(posExtraValues)); }
Hinweis
Dieser Code kann nicht von ClassWizard bearbeitet werden und sollte nur außerhalb der speziellen Formatkommentare verwendet werden.
Schreiben eines benutzerdefinierten RFX
Wenn Sie eine eigene benutzerdefinierte RFX-Funktion schreiben möchten, wird empfohlen, eine vorhandene RFX-Funktion zu kopieren und in Ihre eigenen Zwecke zu ändern. Die Auswahl des richtigen RFX zum Kopieren kann Ihre Arbeit erheblich vereinfachen. Einige RFX-Funktionen weisen einige eindeutige Eigenschaften auf, die Sie berücksichtigen sollten, wenn Sie entscheiden, welche Kopiert werden soll.
RFX_Long
und RFX_Int
: Dies sind die einfachsten RFX-Funktionen. Der Datenwert benötigt keine spezielle Interpretation, und die Datengröße ist fest.
RFX_Single
und RFX_Double
: Wie RFX_Long und RFX_Int oben sind diese Funktionen einfach und können die Standardimplementierung umfassend nutzen. Sie werden in dbflt.cpp anstelle von dbrfx.cpp gespeichert, um das Laden der Laufzeit-Gleitkommabibliothek nur zu ermöglichen, wenn sie explizit referenzieren.
RFX_Text
and RFX_Binary
: These two functions preallocate a static buffer to hold string/binary information, and must register these buffers with ODBC SQLBindCol instead of registration &value. Aus diesem Fall verfügen diese beiden Funktionen über eine Vielzahl von Sonderfallcode.
RFX_Date
: ODBC gibt Datums- und Uhrzeitinformationen in ihrer eigenen TIMESTAMP_STRUCT Datenstruktur zurück. Diese Funktion weist eine TIMESTAMP_STRUCT dynamisch als "Proxy" zum Senden und Empfangen von Datums-/Uhrzeitdaten zu. Verschiedene Vorgänge müssen die Datums- und Uhrzeitinformationen zwischen dem C++ CTime
-Objekt und dem TIMESTAMP_STRUCT Proxy übertragen. Dies erschwert diese Funktion erheblich, aber es ist ein gutes Beispiel für die Verwendung eines Proxys für die Datenübertragung.
RFX_LongBinary
: Dies ist die einzige RFX-Funktion der Klassenbibliothek, die keine Spaltenbindung zum Empfangen und Senden von Daten verwendet. Diese Funktion ignoriert den BindFieldToColumn-Vorgang und weist stattdessen während des Fixup-Vorgangs Speicher für die eingehenden SQL_LONGVARCHAR oder SQL_LONGVARBINARY Daten zu, und führt dann einen SQLGetData-Aufruf aus, um den Wert in den zugewiesenen Speicher abzurufen. Bei der Vorbereitung auf das Senden von Datenwerten an die Datenquelle (z. B. NameValue- und Wertvorgänge) verwendet diese Funktion die DATA_AT_EXEC Funktionalität von ODBC. Weitere Informationen zum Arbeiten mit SQL_LONGVARBINARY und SQL_LONGVARCHARs finden Sie in technischem Hinweis 45 .
Beim Schreiben ihrer eigenen RFX_ -Funktion können CFieldExchange::Default
Sie häufig einen bestimmten Vorgang implementieren. Sehen Sie sich die Implementierung von Default für den betreffenden Vorgang an. Wenn sie den Vorgang ausführt, den Sie in Ihrer RFX_ -Funktion schreiben, können Sie an die CFieldExchange::Default
. Beispiele für das Aufrufen CFieldExchange::Default
in "dbrfx.cpp"
Es ist wichtig, am Anfang der RFX-Funktion aufzurufen IsFieldType
und sofort zurückzugeben, wenn FALSCH zurückgegeben wird. Dieser Mechanismus verhindert, dass Parametervorgänge für outputColumns ausgeführt werden und umgekehrt (z. B. das Aufrufen BindParam
einer outputColumn). Darüber hinaus IsFieldType
verfolgt automatisch die Anzahl der OutputColumns (m_nFields) und Params (m_nParams).
Siehe auch
Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet