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. ), IsFieldDirtyfü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-ParameterCObject::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 soll

  • BindFieldToColumn — Gibt an, wo ODBC-Ausgabedaten abrufen/ablegen müssen.

  • Fixup — Längen festlegen CString/CByteArray , NULL-Statusbit festlegen

  • MarkForAddNew— Mark modifiziert if value has changed since AddNew call

  • MarkForUpdate— Mark modifiziert if value has changed since Edit call

  • Name— Anfügen von Feldnamen für Felder, die als modifiziert markiert sind

  • NameValue— Fügen Sie "<Spaltenname>=" für Felder an, die modifiziert

  • Value — Fügen Sie "" gefolgt von Trennzeichen an, z. B. ',' oder '

  • SetFieldDirty— Festlegen des Statusbits modifiziert (d. h. geändert) feld

  • SetFieldNull — Festlegen des Statusbits, das den Nullwert für das Feld angibt

  • IsFieldDirty— Rückgabewert modifiziert Statusbits

  • IsFieldNull — Rückgabewert des Nullstatusbits

  • IsFieldNullable — True zurückgeben, wenn das Feld NULL-Werte enthalten kann

  • StoreField — Archivfeldwert

  • LoadField — Wert des archivierten Felds erneut laden

  • GetFieldInfoValue — Allgemeine Informationen zu einem Feld zurückgeben

  • GetFieldInfoOrdinal — 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