Freigeben über


TN045: MFC- und Datenbankunterstützung für LONGVARCHAR und LONGVARBINARY

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 beschrieben, wie Sie die ODBC-SQL_LONGVARCHAR und SQL_LONGVARBINARY Datentypen mithilfe der MFC-Datenbankklassen abrufen und senden.

Übersicht über long Varchar/Varbinary Support

Die ODBC-SQL_LONG_VARCHAR und SQL_LONGBINARY Datentypen (hier als lange Datenspalten bezeichnet) können große Datenmengen enthalten. Es gibt drei Möglichkeiten, wie Sie diese Daten behandeln können:

  • Binden sie an ein CString/CByteArray.

  • Binden sie an ein CLongBinary.

  • Binden Sie ihn überhaupt nicht, und rufen Sie den langen Datenwert manuell ab, unabhängig von den Datenbankklassen.

Jede der drei Methoden hat Vor- und Nachteile.

Lange Datenspalten werden für Parameter für eine Abfrage nicht unterstützt. Sie werden nur für outputColumns unterstützt.

Binden einer langen Datenspalte an eine CString/CByteArray

Vorteile:

Dieser Ansatz ist einfach zu verstehen, und Sie arbeiten mit vertrauten Klassen. Das Framework bietet CFormView Unterstützung für CString DDX_Text. Sie verfügen über viele allgemeine Zeichenfolgen- oder Sammlungsfunktionen mit den CString Und-Klassen CByteArray , und Sie können die Menge des lokal zugewiesenen Arbeitsspeichers steuern, um den Datenwert zu speichern. Das Framework Standard eine alte Kopie von Felddaten während Edit oder AddNew Funktionsaufrufen enthält, und das Framework kann automatisch Änderungen an den Daten für Sie erkennen.

Hinweis

Da CString für die Arbeit an Zeichendaten und CByteArray für die Arbeit an Binärdaten entwickelt wurde, empfiehlt es sich, die Zeichendaten (SQL_LONGVARCHAR) und die Binärdaten (SQL_LONGVARBINARY) in CStringCByteArray.

Die RFX-Funktionen für CString und CByteArray verfügen über ein zusätzliches Argument, mit dem Sie die Standardgröße des zugewiesenen Speichers außer Kraft setzen können, um den abgerufenen Wert für die Datenspalte zu speichern. Beachten Sie das nMaxLength-Argument in den folgenden Funktionsdeklarationen:

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);

Wenn Sie eine lange Datenspalte in eine oder CByteArrayeine CString lange Datenspalte abrufen, beträgt die maximale zurückgegebene Datenmenge standardmäßig 255 Byte. Alles darüber hinaus wird ignoriert. In diesem Fall löst das Framework die Ausnahme AFX_SQL_ERROR_DATA_TRUNCATED aus. Glücklicherweise können Sie nMaxLength explizit auf höhere Werte erhöhen, bis maxINT.

Hinweis

Der Wert von nMaxLength wird von MFC verwendet, um den lokalen Puffer der SQLBindColumn Funktion festzulegen. Dies ist der lokale Puffer für die Speicherung der Daten und wirkt sich nicht tatsächlich auf die Vom ODBC-Treiber zurückgegebene Datenmenge aus. RFX_Text und RFX_Binary führen Sie nur einen Aufruf aus SQLFetch , um die Daten aus der Back-End-Datenbank abzurufen. Jeder ODBC-Treiber hat eine andere Einschränkung für die Datenmenge, die sie in einem einzigen Abruf zurückgeben können. Dieser Grenzwert kann wesentlich kleiner als der in nMaxLength festgelegte Wert sein, in diesem Fall wird die Ausnahme ausgelöst, AFX_SQL_ERROR_DATA_TRUNCATED ausgelöst wird. Wechseln Sie unter diesen Umständen zur Verwendung RFX_LongBinary anstelle oder RFX_Text RFX_Binary so, dass alle Daten abgerufen werden können.

ClassWizard bindet eine SQL_LONGVARCHAR an eine CStringoder eine SQL_LONGVARBINARY für CByteArray Sie. Wenn Sie mehr als 255 Bytes zuordnen möchten, in die Sie die lange Datenspalte abrufen, können Sie dann einen expliziten Wert für nMaxLength angeben.

Wenn eine lange Datenspalte an ein CString Oder oder CByteArrayoder gebunden ist, funktioniert das Aktualisieren des Felds genauso wie beim Binden an eine SQL_VARCHAR oder SQL_VARBINARY. Während des Vorgangs Editwird der Datenwert zwischengespeichert und später verglichen, um Update Änderungen am Datenwert zu erkennen und die Dirty- und Null-Werte für die Spalte entsprechend festzulegen.

Binden einer langen Datenspalte an ein CLongBinary

Wenn Ihre lange Datenspalte möglicherweise mehr MAXINT-Bytes von Daten enthält, sollten Sie es wahrscheinlich in Betracht ziehen, sie in eine CLongBinary.

Vorteile:

Dadurch wird eine gesamte lange Datenspalte bis zum verfügbaren Arbeitsspeicher abgerufen.

Nachteile:

Die Daten werden im Arbeitsspeicher gespeichert. Dieser Ansatz ist auch unertragbar teuer für sehr große Datenmengen. Sie müssen das gebundene Datenelement aufrufen SetFieldDirty , um sicherzustellen, dass das Feld in einem Update Vorgang enthalten ist.

Wenn Sie lange Datenspalten in eine CLongBinaryDatenspalte abrufen, überprüfen die Datenbankklassen die Gesamtgröße der langen Datenspalte, und weisen Sie dann ein HGLOBAL Speichersegment zu, das groß genug ist, um den gesamten Datenwert zu speichern. Die Datenbankklassen rufen dann den gesamten Datenwert in der zugeordneten HGLOBALDatei ab.

Wenn die Datenquelle die erwartete Größe der langen Datenspalte nicht zurückgeben kann, löst das Framework die Ausnahme AFX_SQL_ERROR_SQL_NO_TOTAL aus. Wenn der Versuch, den HGLOBAL Fehler zuzuweisen, wird eine Standardspeicher ausnahme ausgelöst.

ClassWizard bindet eine SQL_LONGVARCHAR oder SQL_LONGVARBINARY für CLongBinary Sie. Wählen Sie CLongBinary im Dialogfeld "Membervariable hinzufügen" als Variablentyp aus. ClassWizard fügt dann einen RFX_LongBinary Aufruf zu Ihrem DoFieldExchange Aufruf hinzu und erhöht die Gesamtanzahl der gebundenen Felder.

Um lange Datenspaltenwerte zu aktualisieren, stellen Sie zunächst sicher, dass die zugeordnete HGLOBAL Daten groß genug ist, um die neuen Daten zu speichern, indem Sie "::GlobalSize" für das m_hData Mitglied der Datei CLongBinaryaufrufen. Wenn sie zu klein ist, geben Sie die HGLOBAL entsprechende Größe frei, und weisen Sie sie zu. Legen Sie dann m_dwDataLength fest, um die neue Größe widerzuspiegeln.

Andernfalls können Sie, wenn m_dwDataLength größer als die Größe der daten ist, die Sie ersetzen, entweder freigeben und neu zuordnen HGLOBALoder sie zugeordnet lassen. Stellen Sie sicher, dass Sie die Anzahl der Bytes angeben, die tatsächlich in m_dwDataLength verwendet werden.

So wird's geht beim Aktualisieren eines CLongBinary-Vorgangs

Es ist nicht notwendig, zu verstehen, wie ein Update funktioniert CLongBinary , aber es kann hilfreich sein, wie lange Datenwerte an eine Datenquelle gesendet werden, wenn Sie diese dritte Methode auswählen, wie unten beschrieben.

Hinweis

Damit ein CLongBinary Feld in eine Aktualisierung einbezogen werden kann, müssen Sie das Feld explizit aufrufen SetFieldDirty . Wenn Sie eine Änderung an einem Feld vornehmen, einschließlich der Einstellung null, müssen Sie aufrufen SetFieldDirty. Sie müssen auch den zweiten Parameter mit FALSE aufrufenSetFieldNull, um das Feld als Wert zu kennzeichnen.

Beim Aktualisieren eines CLongBinary Felds verwenden die Datenbankklassen den DATA_AT_EXEC Mechanismus von ODBC (siehe ODBC-Dokumentation zum SQLSetPosRgbValue-Argument). Wenn das Framework die Einfüge- oder Aktualisierungsanweisung vorbereitet, anstatt auf die HGLOBAL mit den Daten zu verweisen, wird die Adresse der CLongBinary Spalte stattdessen als Wert der Spalte festgelegt, und der Längenindikator, der auf SQL_DATA_AT_EXEC festgelegt ist. Wenn die Aktualisierungsanweisung später an die Datenquelle gesendet wird, SQLExecDirect wird SQL_NEED_DATA zurückgegeben. Dadurch wird das Framework benachrichtigt, dass der Wert des Param für diese Spalte tatsächlich die Adresse einer .CLongBinary Das Framework ruft einmal mit einem kleinen Puffer auf SQLGetData , wobei erwartet wird, dass der Treiber die tatsächliche Länge der Daten zurückgibt. Wenn der Treiber die tatsächliche Länge des binären großen Objekts (BLOB) zurückgibt, wird MFC so viel Speicherplatz wie nötig neu zugeordnet, um das BLOB abzurufen. Wenn die Datenquelle SQL_NO_TOTAL zurückgibt und angibt, dass die Größe des BLOB nicht bestimmt werden kann, erstellt MFC kleinere Blöcke. Die Standard-Anfangsgröße ist 64K, und nachfolgende Blöcke sind doppelt so groß wie die Größe. Beispielsweise ist die zweite 128K, der dritte ist 256K usw. Die anfängliche Größe kann konfiguriert werden.

Keine Bindung: Direktes Abrufen/Senden von Daten aus ODBC mit SQLGetData

Mit dieser Methode umgehen Sie die Datenbankklassen vollständig und behandeln die lange Datenspalte selbst.

Vorteile:

Sie können bei Bedarf Daten auf dem Datenträger zwischenspeichern oder dynamisch entscheiden, wie viele Daten abgerufen werden sollen.

Nachteile:

Sie erhalten das Framework Edit oder AddNew die Unterstützung nicht, und Sie müssen Code selbst schreiben, um grundlegende Funktionen auszuführen (Delete funktioniert jedoch, da es sich nicht um einen Vorgang auf Spaltenebene handelt).

In diesem Fall muss sich die lange Datenspalte in der Auswahlliste des Recordsets befinden, aber nicht an das Framework gebunden werden. Eine Möglichkeit hierzu besteht darin, Ihre eigene SQL-Anweisung über GetDefaultSQL oder als lpszSQL-Argument an CRecordsetdie Open Funktion zu liefern und die zusätzliche Spalte nicht mit einem RFX_ Funktionsaufruf zu binden. ODBC erfordert, dass ungebundene Felder rechts neben gebundenen Feldern angezeigt werden. Fügen Sie also die ungebundene Spalte oder Spalten am Ende der Auswahlliste hinzu.

Hinweis

Da Ihre lange Datenspalte nicht an das Framework gebunden ist, werden Änderungen daran nicht mit CRecordset::Update Aufrufen behandelt. Sie müssen die erforderlichen SQL INSERT- und UPDATE-Anweisungen selbst erstellen und senden.

Siehe auch

Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet