TN045: Dukungan MFC/Database untuk Long Varchar/Varbinary
Catatan
Catatan teknis berikut belum diperbarui sejak pertama kali disertakan dalam dokumentasi online. Akibatnya, beberapa prosedur dan topik mungkin kedaluarsa atau salah. Untuk informasi terbaru, disarankan agar Anda mencari topik yang menarik dalam indeks dokumentasi online.
Catatan ini menjelaskan cara mengambil dan mengirim SQL_LONGVARCHAR ODBC dan SQL_LONGVARBINARY jenis data menggunakan kelas database MFC.
Gambaran Umum Dukungan Long Varchar/Varbinary
Odbc SQL_LONG_VARCHAR dan SQL_LONGBINARY jenis data (disebut di sini selama kolom data) dapat menyimpan data dalam jumlah besar. Ada 3 cara untuk menangani data ini:
Ikat ke
CString
/CByteArray
.Ikat ke
CLongBinary
.Jangan mengikatnya sama sekali dan mengambil dan mengirim nilai data panjang secara manual, independen dari kelas database.
Masing-masing dari tiga metode memiliki kelebihan dan kekurangan.
Kolom data panjang tidak didukung untuk parameter ke kueri. Mereka hanya didukung untuk outputColumns.
Mengikat Kolom Data Panjang ke CString/CByteArray
Keuntungan:
Pendekatan ini mudah dipahami, dan Anda bekerja dengan kelas yang akrab. Kerangka kerja menyediakan CFormView
dukungan untuk CString
dengan DDX_Text
. Anda memiliki banyak fungsionalitas string atau koleksi umum dengan CString
kelas dan CByteArray
, dan Anda dapat mengontrol jumlah memori yang dialokasikan secara lokal untuk menyimpan nilai data. Kerangka kerja mempertahankan salinan lama data bidang selama Edit
AddNew
atau panggilan fungsi, dan kerangka kerja dapat secara otomatis mendeteksi perubahan pada data untuk Anda.
Catatan
Karena CString
dirancang untuk mengerjakan data karakter, dan CByteArray
untuk mengerjakan data biner, disarankan agar Anda memasukkan data karakter (SQL_LONGVARCHAR) ke dalam CString
, dan data biner (SQL_LONGVARBINARY) ke dalam CByteArray
.
Fungsi RFX untuk CString
dan CByteArray
memiliki argumen tambahan yang memungkinkan Anda mengambil alih ukuran default memori yang dialokasikan untuk menahan nilai yang diambil untuk kolom data. Perhatikan argumen nMaxLength dalam deklarasi fungsi berikut:
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);
Jika Anda mengambil kolom data panjang ke dalam CString
atau CByteArray
, jumlah data maksimum yang dikembalikan adalah, secara default, 255 byte. Apa pun di luar ini diabaikan. Dalam hal ini, kerangka kerja akan melemparkan pengecualian AFX_SQL_ERROR_DATA_TRUNCATED. Untungnya, Anda dapat secara eksplisit meningkatkan nMaxLength ke nilai yang lebih besar, hingga MAXINT.
Catatan
Nilai nMaxLength digunakan oleh MFC untuk mengatur buffer SQLBindColumn
lokal fungsi. Ini adalah buffer lokal untuk penyimpanan data dan sebenarnya tidak memengaruhi jumlah data yang dikembalikan oleh driver ODBC. RFX_Text
dan RFX_Binary
hanya melakukan satu panggilan menggunakan SQLFetch
untuk mengambil data dari database back-end. Setiap driver ODBC memiliki batasan yang berbeda pada jumlah data yang dapat mereka kembalikan dalam satu pengambilan. Batas ini mungkin jauh lebih kecil daripada nilai yang ditetapkan di nMaxLength, dalam hal ini pengecualian AFX_SQL_ERROR_DATA_TRUNCATED akan dilemparkan. Dalam keadaan ini, beralihlah menggunakan RFX_LongBinary
alih-alih RFX_Text
atau RFX_Binary
sehingga semua data dapat diambil.
ClassWizard akan mengikat SQL_LONGVARCHAR ke CString
, atau SQL_LONGVARBINARY untuk CByteArray
Anda. Jika Anda ingin mengalokasikan lebih dari 255 byte tempat Anda mengambil kolom data panjang, Anda kemudian dapat memberikan nilai eksplisit untuk nMaxLength.
Ketika kolom data panjang terikat ke CString
atau CByteArray
, memperbarui bidang berfungsi sama seperti ketika terikat ke SQL_VARCHAR atau SQL_VARBINARY. Selama Edit
, nilai data di-cache dan kemudian dibandingkan ketika Update
dipanggil untuk mendeteksi perubahan pada nilai data dan mengatur nilai Kotor dan Null untuk kolom dengan tepat.
Mengikat Kolom Data Panjang ke CLongBinary
Jika kolom data panjang Anda mungkin berisi lebih banyak byte data MAXINT , Anda mungkin harus mempertimbangkan untuk mengambilnya menjadi CLongBinary
.
Keuntungan:
Ini mengambil seluruh kolom data panjang, hingga memori yang tersedia.
Kekurangan:
Data disimpan dalam memori. Pendekatan ini juga dilarang mahal untuk data dalam jumlah yang sangat besar. Anda harus memanggil SetFieldDirty
anggota data terikat untuk memastikan bidang disertakan dalam Update
operasi.
Jika Anda mengambil kolom data panjang ke dalam CLongBinary
, kelas database akan memeriksa ukuran total kolom data panjang, lalu mengalokasikan segmen memori yang HGLOBAL
cukup besar untuk menahannya seluruh nilai data. Kelas database kemudian mengambil seluruh nilai data ke dalam yang dialokasikan HGLOBAL
.
Jika sumber data tidak dapat mengembalikan ukuran kolom data panjang yang diharapkan, kerangka kerja akan melemparkan pengecualian AFX_SQL_ERROR_SQL_NO_TOTAL. Jika upaya untuk mengalokasikan HGLOBAL
gagal, pengecualian memori standar akan dilemparkan.
ClassWizard akan mengikat SQL_LONGVARCHAR atau SQL_LONGVARBINARY untuk CLongBinary
Anda. Pilih CLongBinary
sebagai Jenis Variabel dalam dialog Tambahkan Variabel Anggota. ClassWizard kemudian akan menambahkan RFX_LongBinary
panggilan ke panggilan Anda DoFieldExchange
dan menambah jumlah total bidang terikat.
Untuk memperbarui nilai kolom data panjang, pertama-tama pastikan yang dialokasikan HGLOBAL
cukup besar untuk menyimpan data baru Anda dengan memanggil ::GlobalSize pada anggota m_hData dari CLongBinary
. Jika terlalu kecil, lepaskan HGLOBAL
dan alokasikan satu ukuran yang sesuai. Kemudian atur m_dwDataLength untuk mencerminkan ukuran baru.
Jika tidak, jika m_dwDataLength lebih besar dari ukuran data yang Anda ganti, Anda dapat membebaskan dan merealokasi HGLOBAL
, atau membiarkannya dialokasikan. Pastikan untuk menunjukkan jumlah byte yang benar-benar digunakan dalam m_dwDataLength.
Cara Memperbarui CLongBinary Bekerja
Tidak perlu memahami cara memperbarui pekerjaan CLongBinary
, tetapi mungkin berguna sebagai contoh tentang cara mengirim nilai data panjang ke sumber data, jika Anda memilih metode ketiga ini, dijelaskan di bawah ini.
Catatan
Agar CLongBinary
bidang disertakan dalam pembaruan, Anda harus secara eksplisit memanggil SetFieldDirty
bidang tersebut. Jika Anda membuat perubahan pada bidang, termasuk mengaturnya Null, Anda harus memanggil SetFieldDirty
. Anda juga harus memanggil SetFieldNull
, dengan parameter kedua adalah FALSE, untuk menandai bidang sebagai memiliki nilai.
Saat memperbarui CLongBinary
bidang, kelas database menggunakan mekanisme DATA_AT_EXEC ODBC (lihat dokumentasi ODBC tentang SQLSetPos
argumen rgbValue). Ketika kerangka kerja menyiapkan pernyataan sisipkan atau perbarui, alih-alih menunjuk ke HGLOBAL
yang berisi data, alamat CLongBinary
ditetapkan sebagai nilai kolom sebagai gantinya, dan indikator panjang diatur ke SQL_DATA_AT_EXEC. Nantinya, ketika pernyataan pembaruan dikirim ke sumber data, SQLExecDirect
akan mengembalikan SQL_NEED_DATA. Ini memperingatkan kerangka kerja bahwa nilai param untuk kolom ini sebenarnya adalah alamat .CLongBinary
Kerangka kerja memanggil SQLGetData
sekali dengan buffer kecil, mengharapkan driver mengembalikan panjang data yang sebenarnya. Jika driver mengembalikan panjang aktual objek besar biner (BLOB), MFC merealokasi ruang sebanyak yang diperlukan untuk mengambil BLOB. Jika sumber data mengembalikan SQL_NO_TOTAL, menunjukkan bahwa sumber data tidak dapat menentukan ukuran BLOB, MFC akan membuat blok yang lebih kecil. Ukuran awal default adalah 64K, dan blok berikutnya akan berukuran dua kali lipat; misalnya, yang kedua adalah 128K, yang ketiga adalah 256K, dan sebagainya. Ukuran awal dapat dikonfigurasi.
Tidak Mengikat: Mengambil/Mengirim Data Langsung dari ODBC dengan SQLGetData
Dengan metode ini Anda sepenuhnya melewati kelas database, dan menangani sendiri kolom data panjang.
Keuntungan:
Anda dapat menyimpan data ke disk jika perlu, atau memutuskan secara dinamis berapa banyak data yang akan diambil.
Kekurangan:
Anda tidak mendapatkan kerangka kerja Edit
atau AddNew
dukungan, dan Anda harus menulis kode sendiri untuk melakukan fungsionalitas dasar (Delete
berfungsi meskipun, karena itu bukan operasi tingkat kolom).
Dalam hal ini, kolom data panjang harus berada dalam daftar pemilihan kumpulan rekaman, tetapi tidak boleh terikat dengan kerangka kerja. Salah satu cara untuk melakukan ini adalah dengan memberikan pernyataan SQL Anda sendiri melalui GetDefaultSQL
atau sebagai argumen lpszSQL ke CRecordset
fungsi 's Open
, dan tidak mengikat kolom tambahan dengan panggilan fungsi RFX_. ODBC mengharuskan bidang yang tidak terikat muncul di sebelah kanan bidang terikat, jadi tambahkan kolom atau kolom tidak terikat Anda ke akhir daftar pilih.
Catatan
Karena kolom data panjang Anda tidak terikat oleh kerangka kerja, perubahan pada kolom tersebut tidak akan ditangani dengan CRecordset::Update
panggilan. Anda harus membuat dan mengirim pernyataan SQL INSERT dan UPDATE yang diperlukan sendiri.
Baca juga
Catatan Teknis menurut Angka
Catatan Teknis menurut Kategori