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 CString
CByteArray
.
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 CByteArray
eine 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 CString
oder 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 CByteArray
oder gebunden ist, funktioniert das Aktualisieren des Felds genauso wie beim Binden an eine SQL_VARCHAR oder SQL_VARBINARY. Während des Vorgangs Edit
wird 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 CLongBinary
Datenspalte 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 HGLOBAL
Datei 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 CLongBinary
aufrufen. 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 HGLOBAL
oder 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 SQLSetPos
RgbValue-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 CRecordset
die 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