Bagikan melalui


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 SQLSetPosargumen 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 CRecordsetfungsi '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