TN045: Podpora prostředí MFC a databáze pro typy Long Varchar/Varbinary
Poznámka
Následující technická poznámka se od prvního zahrnutí do online dokumentace neaktualizovala. V důsledku toho můžou být některé postupy a témata zastaralé nebo nesprávné. Nejnovější informace doporučujeme vyhledat v online indexu dokumentace, které vás zajímá.
Tato poznámka popisuje, jak načíst a odeslat datové typy ODBC SQL_LONGVARCHAR a SQL_LONGVARBINARY pomocí databázových tříd MFC.
Přehled podpory Long Varchar/Varbinary
Rozhraní ODBC SQL_LONG_VARCHAR a SQL_LONGBINARY datových typů (označovaných zde jako dlouhé datové sloupce) může obsahovat obrovské množství dat. Tato data můžete zpracovat 3 způsoby:
Svázání s objektem
CString
/CByteArray
.Svázání s objektem
CLongBinary
.Nevážete ji vůbec a načtěte a odešlete dlouhou hodnotu dat ručně nezávisle na třídách databáze.
Každá ze tří metod má výhody a nevýhody.
Dlouhé datové sloupce nejsou podporovány pro parametry dotazu. Podporují se jenom pro outputColumns.
Vytvoření vazby dlouhého datového sloupce na CString/CByteArray
Výhody:
Tento přístup je jednoduchý pro pochopení a pracujete se známými třídami. Architektura poskytuje CFormView
podporu pro CString
DDX_Text
. Máte spoustu obecných funkcí řetězců nebo kolekcí s třídami CString
CByteArray
a můžete řídit množství paměti přidělené místně pro uložení datové hodnoty. Architektura udržuje starou kopii dat polí během Edit
volání funkce nebo AddNew
volání a architektura může automaticky zjišťovat změny dat za vás.
Poznámka
Vzhledem k tomu CString
, že je určen pro práci na znakových datech a CByteArray
pro práci s binárními daty, doporučuje se vložit znaková data (SQL_LONGVARCHAR) CString
a binární data (SQL_LONGVARBINARY) do CByteArray
.
Funkce RFX pro CString
a CByteArray
mají další argument, který umožňuje přepsat výchozí velikost přidělené paměti pro uložení načtené hodnoty datového sloupce. Všimněte si argumentu nMaxLength v následujících deklarací funkce:
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);
Pokud načtete dlouhý datový sloupec do CString
nebo CByteArray
, maximální vrácené množství dat je ve výchozím nastavení 255 bajtů. Cokoli, co je nad tím, je ignorováno. V tomto případě architektura vyvolá výjimku AFX_SQL_ERROR_DATA_TRUNCATED. Naštěstí můžete explicitně zvýšit hodnotu nMaxLength na vyšší hodnoty až na MAXINT.
Poznámka
Hodnota nMaxLength je používán mfc k nastavení místní vyrovnávací paměti SQLBindColumn
funkce. Toto je místní vyrovnávací paměť pro ukládání dat a ve skutečnosti nemá vliv na množství dat vrácených ovladačem ODBC. RFX_Text
a RFX_Binary
proveďte pouze jedno volání k SQLFetch
načtení dat z back-endové databáze. Každý ovladač ODBC má jiné omezení množství dat, která mohou vrátit v jednom načtení. Tento limit může být mnohem menší než hodnota nastavená v nMaxLength, v takovém případě bude vyvolán výjimka AFX_SQL_ERROR_DATA_TRUNCATED . Za těchto okolností přepněte na použití RFX_LongBinary
místo RFX_Text
nebo RFX_Binary
tak, aby se všechna data mohly načíst.
TřídaWizard vytvoří vazbu SQL_LONGVARCHAR k objektu CString
nebo SQL_LONGVARBINARY k CByteArray
vám. Pokud chcete přidělit více než 255 bajtů, do kterých načtete dlouhý datový sloupec, můžete zadat explicitní hodnotu pro nMaxLength.
Pokud je dlouhý datový sloupec vázán na nebo CString
CByteArray
, aktualizace pole funguje stejně jako když je vázán na SQL_VARCHAR nebo SQL_VARBINARY. Během Edit
této doby se datová hodnota ukládá do mezipaměti a později se porovná, když Update
je volána, aby se zjistily změny hodnoty dat, a správně nastavte hodnoty Dirty a Null pro sloupec.
Vytvoření vazby dlouhého datového sloupce s CLongBinary
Pokud váš dlouhý datový sloupec může obsahovat více bajtů MAXINT dat, měli byste zvážit jeho načtení do CLongBinary
.
Výhody:
Tím se načte celý dlouhý datový sloupec až do dostupné paměti.
Nevýhody:
Data se uchovávají v paměti. Tento přístup je také pro velmi velké objemy dat příliš nákladný. Musíte volat SetFieldDirty
vázaného datového člena, aby bylo zajištěno, že pole je součástí Update
operace.
Pokud načtete dlouhé datové sloupce do CLongBinary
datového sloupce , třídy databáze zkontrolují celkovou velikost dlouhého datového sloupce a pak přidělí HGLOBAL
segment paměti dostatečně velký, aby ho držela celou hodnotu dat. Třídy databáze pak načtou celou hodnotu dat do přiděleného HGLOBAL
.
Pokud zdroj dat nemůže vrátit očekávanou velikost dlouhého datového sloupce, architektura vyvolá výjimku AFX_SQL_ERROR_SQL_NO_TOTAL. Pokud se pokus o přidělení HGLOBAL
nezdaří, vyvolá se standardní výjimka paměti.
TřídaWizard sváže SQL_LONGVARCHAR nebo SQL_LONGVARBINARY s CLongBinary
vámi. V dialogovém okně Přidat členské proměnné vyberte CLongBinary
typ proměnné. TřídaWizard pak přidá RFX_LongBinary
volání do volání DoFieldExchange
a zvýší celkový počet vázaných polí.
Pokud chcete aktualizovat hodnoty dlouhých datových sloupců, nejprve se ujistěte, že je přidělený HGLOBAL
dostatečně velký, aby se nová data držela voláním ::GlobalSize na m_hData členu CLongBinary
. Pokud je příliš malý, uvolněte HGLOBAL
a přidělte jednu odpovídající velikost. Potom nastavte m_dwDataLength tak, aby odrážely novou velikost.
V opačném případě pokud je m_dwDataLength větší než velikost dat, která nahrazujete, můžete buď uvolnit a znovu přidělit HGLOBAL
, nebo ji ponechat přidělenou. Nezapomeňte určit počet bajtů, které se ve m_dwDataLength skutečně používají.
Jak aktualizace CLongBinary funguje
Není nutné pochopit, jak funguje aktualizace CLongBinary
, ale může být užitečné jako příklad odesílání dlouhých hodnot dat do zdroje dat, pokud zvolíte tuto třetí metodu popsanou níže.
Poznámka
Aby bylo možné CLongBinary
pole zahrnout do aktualizace, musíte pro toto pole explicitně volat SetFieldDirty
. Pokud provedete nějakou změnu pole, včetně nastavení null, musíte volat SetFieldDirty
. Musíte také volat SetFieldNull
, s druhým parametrem false, který označuje pole jako hodnotu.
Při aktualizaci CLongBinary
pole používají databázové třídy mechanismus DATA_AT_EXEC ODBC (viz dokumentace ODBC k SQLSetPos
argumentu rgbValue). Když architektura připraví příkaz insert nebo update místo odkazování na HGLOBAL
obsahující data, adresa CLongBinary
sloupce se místo toho nastaví jako hodnota sloupce a indikátor délky nastavený na SQL_DATA_AT_EXEC. Později, když se příkaz update odešle do zdroje dat, SQLExecDirect
vrátí SQL_NEED_DATA. Tím se upozorní na architekturu, že hodnota parametru pro tento sloupec je ve skutečnosti adresa CLongBinary
. Architektura volá SQLGetData
jednou s malou vyrovnávací pamětí a očekává, že ovladač vrátí skutečnou délku dat. Pokud ovladač vrátí skutečnou délku binárního velkého objektu (OBJEKT BLOB), mfc přeloží tolik místa, kolik je potřeba k načtení objektu BLOB. Pokud zdroj dat vrátí SQL_NO_TOTAL, což znamená, že nemůže určit velikost objektu BLOB, mfc vytvoří menší bloky. Výchozí počáteční velikost je 64 kB a následné bloky budou zdvojnásobit velikost; Druhá bude například 128 tisíc, třetí bude 256 K atd. Počáteční velikost je konfigurovatelná.
Nevazbu: Načítání a odesílání dat přímo z rozhraní ODBC pomocí SQLGetData
Pomocí této metody zcela vynecháte databázové třídy a sami se zabýváte dlouhými datovými sloupci.
Výhody:
V případě potřeby můžete data ukládat na disk do mezipaměti nebo se dynamicky rozhodnout, kolik dat se má načíst.
Nevýhody:
Nemáte architekturu Edit
ani AddNew
podporu a kód musíte napsat sami, abyste mohli provádět základní funkce (Delete
funguje, protože se nejedná o operaci na úrovni sloupce).
V tomto případě musí být dlouhý datový sloupec v seznamu výběrů sady záznamů, ale neměl by být svázán s architekturou. Jedním ze způsobů, jak to udělat, je zadat vlastní příkaz SQL prostřednictvím GetDefaultSQL
nebo jako argument lpszSQL pro CRecordset
Open
funkci a nevázat extra sloupec s voláním funkce RFX_. Rozhraní ODBC vyžaduje, aby se nevázaná pole zobrazovala napravo od vázaných polí, takže na konec seznamu pro výběr přidejte nevázaný sloupec nebo sloupce.
Poznámka
Vzhledem k tomu, že dlouhý datový sloupec není vázán architekturou, změny v něm nebudou zpracovány voláními CRecordset::Update
. Musíte vytvořit a odeslat požadované příkazy SQL INSERT a UPDATE sami.
Viz také
Technické poznámky podle čísel
Technické poznámky podle kategorií