ID Artikel: 194975 - Kajian Terakhir: 19 September 2011 - Revisi: 2.0

Bagaimana untuk membaca dan menulis BLOBs menggunakan GetChunk dan AppendChunk

Tips SistemThis article applies to a different operating system than the one you are using. Article content that may not be relevant to you is disabled.
Untuk Microsoft Visual Basic.NET versi artikel ini, lihat 317034  (http://support.microsoft.com/kb/317034/EN-US/ ) .
Untuk Microsoft Visual Basic.NET versi artikel ini, lihat 316887  (http://support.microsoft.com/kb/316887/EN-US/ ) .

Pada Halaman ini

Perbesar semua | Perkecil semua

RINGKASAN

Artikel ini menjelaskan cara untuk membaca dan menulis objek-objek besar biner (BLOBs) menggunakan metode GetChunk dan AppendChunk terhadap bidang dalam ADO. Itu juga termasuk kode contoh menggunakan database contoh NWIND.

INFORMASI LEBIH LANJUT

GetChunk dan AppendChunk metode yang bekerja dengan LongVarChar, LongVarWChar, dan LongVarBinary kolom jenis, juga dikenal sebagai kolom teks, NTEXT, dan gambar, Microsoft SQL Server, dan sebagai bidang MEMO dan OLE di Microsoft Jet database. Anda dapat mengidentifikasi ini kolom dalam ADO dengan menguji jenis properti medan untuk nilai-nilai adLongVarChar, adLongVarWChar, dan adLongVarBinary. Anda juga bisa menguji properti atribut lapangan untuk bendera adFldLong:
If fld.Attributes And adFldLong Then
   ' You can use GetChunk/AppendChunk
				
Panjang kolom yang biasanya disebut sebagai gumpalan (biner besar OBjects) bahkan Meskipun mereka mungkin berisi data teks. Contoh kode di bawah ini menyediakan dua rutinitas, BlobToFile dan FileToBlob.

BlobToFile

BlobToFile menentukan tipe data lapangan dan yang tiga metode digunakan untuk menulis BLOB data ke disk file. Jika BLOB data kecil cukup, itu akan referensi nilai bidang ini secara keseluruhan tanpa panggilan GetChunk. Jika ukuran GUMPALAN tidak diketahui, itu akan memanggil WriteFromUnsizedBinary atau WriteFromUnsizedText untuk menulis data. Ini kurang efisien dalam istilah membuat salinan tambahan data di memori lokal daripada WriteFromBinary dan WriteFromText rutinitas yang digunakan ketika ukuran BLOB data dikenal:
    BlobToFile                Calls one of the below routines to use GetChunk
    WriteFromBinary         Writes a LongVarBinary of known size to disk
    WriteFromUnsizedBinary  Writes a LongVarBinary on unknown size
    WriteFromText           Writes a LongVarChar of known size
    WriteFromUnsizedText    Writes a LongVarChar of unknown size
				

FileToBlob

FileToBlob menentukan apakah akan menggunakan AppendChunk atau langsung menetapkan data untuk bidang GUMPALAN yang didasarkan pada ukuran file. Karena ukuran file dapat selalu ditentukan, ada rutinitas "Unsized" tidak ada berada dalam kode contoh BlobToFile:
    FileToBlob          Calls one of the below routines to use AppendChunk
    ReadToBinary      Reads a file into a LongVarBinary column
    ReadToText        Reads a file into a LongVarChar column
				

Contoh

Contoh kode untuk BlobToFile dan FileToBlob disimpan dalam modul, sementara tes kode adalah di belakang bentuk standar. Tes kode menggunakan masing-masing tiga metode untuk menyimpan ke disk foto (gambar/OLE/LongVarBinary) dan catatan Bidang (teks/MEMO/LongVarChar/LongVarWChar) untuk Andrew Fuller dari tabel karyawan database NWIND. Kemudian membaca file kembali dan menciptakan enam baru Catatan, membaca masing-masing dari tiga set file melalui dua berbeda membaca metode.CATATAN: Menggunakan ADO 2,1 dan belakangan, Anda mungkin melihat kesalahan berikut pada baris kode:
Data = fld.GetChunk(BLOCK_SIZE) :

        Run-time error '94':
        Invalid use of Null
				
ADO 2,1 dan kemudian mungkin laporan ActualSize properti dari lapangan GUMPALAN jenis teks sebagai dua kali jumlah karakter. Ini benar jika bidang GUMPALAN berisi Unicode teks, karena menggunakan Unicode byte 2 per karakter. Ini salah jika bidang GUMPALAN berisi teks ANSI, yang menggunakan 1-byte per karakter. Jika ActualSize adalah dua kali panjang medan ANSI, kemudian GetChunk akhirnya mencoba untuk melewati akhir bidang.

Anda dapat melihat perilaku ini dalam skenario berikut, dan mungkin melihatnya dalam skenario lain:

Skenario 1:

Dengan SQL Server 7 NTEXT lapangan (ANSI teks), menggunakan baik OLE DB penyedia untuk SQL Server atau penyedia ODBC dengan SQL Server ODBC driver.

Perhatikan bahwa menggunakan SQL Server teks lapangan (Unicode) bekerja dengan kedua penyedia.

Skenario 2:

Dengan akses 97 MEMO bidang dan dengan akses 2000 MEMO bidang dengan atau tanpa kompresi Unicode, menggunakan baik OLE DB penyedia untuk Jet 4.0 atau penyedia ODBC dengan pengandar Jet ODBC 4.0, ODBCJT32.DLL.

Perhatikan bahwa, dengan akses 97 MEMO bidang, baik OLE DB penyedia untuk Jet 3.51 dan penyedia ODBC dengan pengandar Jet ODBC 3.51 bekerja dengan benar.

Ada beberapa kemungkinan workarounds untuk galat Run-time '94':
  • Menggunakan rs.FieldName.ActualSize \ 2 bukannya rs.FieldName.ActualSize. Ini memecahkan masing-masing skenario tertentu yang tercantum di atas.

  • Menggunakan metode 2 atau 3 di bawah ini, yang tidak bergantung pada ActualSize properti.

Menyiapkan Data

  1. Di Microsoft Access atau alat lainnya, buka NWIND.MDB.
  2. Buka tabel karyawan (atau bentuk) dan menemukan "Andrew Fuller."
  3. Tempelkan konten file teks besar (antara 30000 dan 60000 byte) ke catatan lapangan.
  4. Simpan perubahan dan keluar akses.
  5. Tambahkan datasource ODBC yang menunjuk ke NWIND.MDB file.

Contoh kode

  1. Membuat proyek Visual Basic baru dari proyek menu, pilih referensi dan pilih perpustakaan objek Data ActiveX Microsoft atau perpustakaan objek Data ActiveX Microsoft.
  2. Menambahkan dua CommandButtons (cmdSave dan cmdLoad) untuk default form(Form1).
  3. Tambahkan kode berikut. Anda akan memiliki untuk mengubah connect string disediakan pada "cn.Buka"jalur:
          Option Explicit
    
          Private Sub CmdSave_Click()
          Dim cn As ADODB.Connection, rs As ADODB.Recordset, SQL As String
            Set cn = New ADODB.Connection
            Set rs = New ADODB.Recordset
            cn.CursorLocation = adUseServer
            cn.Open "dsn=nwind_jet"   ' *** change this ***
            SQL = "SELECT * FROM Employees WHERE LastName='Fuller'"
            rs.Open SQL, cn, adOpenStatic, adLockReadOnly
          '
          ' Save using GetChunk and known size.
          ' FieldSize (ActualSize) > Threshold arg (16384)
          '
            BlobToFile rs!Photo, "c:\photo1.dat", rs!Photo.ActualSize, 16384
            BlobToFile rs!Notes, "c:\notes1.txt", rs!Notes.ActualSize, 16384
             
          ' Uncomment the next line of code, and comment the line above,
          ' to workaround Runtime error '94': Invalid use of Null
          ' BlobToFile rs!Notes, "c:\notes1.txt", rs!Notes.ActualSize \ 2, 16384
    
          '
          ' Save using GetChunk and unknown size.
          ' FieldSize not specified.
          '
            BlobToFile rs!Photo, "c:\photo2.dat"
            BlobToFile rs!Notes, "c:\notes2.txt"
          '
          ' Save without using GetChunk
          ' FieldSize (ActualSize) < Threshold arg (defaults to 1Mb)
          '
            BlobToFile rs!Photo, "c:\photo3.dat", rs!Photo.ActualSize
            BlobToFile rs!Notes, "c:\notes3.txt", rs!Notes.ActualSize
    
          ' Uncomment the next line of code, and comment the line above,
          '   to workaround Runtime error '94': Invalid use of Null
          ' BlobToFile rs!Notes, "c:\notes3.txt", rs!Notes.ActualSize \ 2
    
            rs.Close
            cn.Close
          End Sub
    
          Private Sub CmdLoad_Click()
          Dim cn As ADODB.Connection, rs As ADODB.Recordset, SQL As String
            Set cn = New ADODB.Connection
            Set rs = New ADODB.Recordset
            cn.CursorLocation = adUseServer
            cn.Open "dsn=ole_db_nwind_jet"
            SQL = "SELECT * FROM Employees"
            rs.Open SQL, cn, adOpenKeyset, adLockOptimistic
          '
          ' Load using AppendChunk
          '
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller11"
            FileToBlob "c:\photo1.dat", rs!Photo, 16384
            FileToBlob "c:\notes1.txt", rs!Notes, 16384
            rs.Update
    
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller21"
            FileToBlob "c:\photo2.dat", rs!Photo, 16384
            FileToBlob "c:\notes2.txt", rs!Notes, 16384
            rs.Update
    
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller31"
            FileToBlob "c:\photo3.dat", rs!Photo, 16384
            FileToBlob "c:\notes3.txt", rs!Notes, 16384
            rs.Update
    
          '
          ' Load without using AppendChunk
          '
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller12"
            FileToBlob "c:\photo1.dat", rs!Photo
            FileToBlob "c:\notes1.txt", rs!Notes
            rs.Update
    
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller22"
            FileToBlob "c:\photo2.dat", rs!Photo
            FileToBlob "c:\notes2.txt", rs!Notes
            rs.Update
    
            rs.AddNew
            rs!FirstName = "Test"
            rs!LastName = "Fuller32"
            FileToBlob "c:\photo3.dat", rs!Photo
            FileToBlob "c:\notes3.txt", rs!Notes
            rs.Update
    
            rs.Close
            cn.Close
          End Sub
    					
  4. Menambahkan modul baru untuk proyek (Module1) dengan kode berikut:
          Option Explicit
    
          Const BLOCK_SIZE = 16384
    
          Sub BlobToFile(fld As ADODB.Field, ByVal FName As String, _
                         Optional FieldSize As Long = -1, _
                         Optional Threshold As Long = 1048576)
          '
          ' Assumes file does not exist
          ' Data cannot exceed approx. 2Gb in size
          '
          Dim F As Long, bData() As Byte, sData As String
            F = FreeFile
            Open FName For Binary As #F
            Select Case fld.Type
              Case adLongVarBinary
                If FieldSize = -1 Then   ' blob field is of unknown size
                  WriteFromUnsizedBinary F, fld
                Else                     ' blob field is of known size
                  If FieldSize > Threshold Then   ' very large actual data
                    WriteFromBinary F, fld, FieldSize
                  Else                            ' smallish actual data
                    bData = fld.Value
                    Put #F, , bData  ' PUT tacks on overhead if use fld.Value
                  End If
                End If
              Case adLongVarChar, adLongVarWChar
                If FieldSize = -1 Then
                  WriteFromUnsizedText F, fld
                Else
                  If FieldSize > Threshold Then
                    WriteFromText F, fld, FieldSize
                  Else
                    sData = fld.Value
                    Put #F, , sData  ' PUT tacks on overhead if use fld.Value
                  End If
                End If
            End Select
            Close #F
          End Sub
    
          Sub WriteFromBinary(ByVal F As Long, fld As ADODB.Field, _
                              ByVal FieldSize As Long)
          Dim Data() As Byte, BytesRead As Long
            Do While FieldSize <> BytesRead
              If FieldSize - BytesRead < BLOCK_SIZE Then
                Data = fld.GetChunk(FieldSize - BLOCK_SIZE)
                BytesRead = FieldSize
              Else
                Data = fld.GetChunk(BLOCK_SIZE)
                BytesRead = BytesRead + BLOCK_SIZE
              End If
              Put #F, , Data
            Loop
          End Sub
    
          Sub WriteFromUnsizedBinary(ByVal F As Long, fld As ADODB.Field)
          Dim Data() As Byte, Temp As Variant
            Do
              Temp = fld.GetChunk(BLOCK_SIZE)
              If IsNull(Temp) Then Exit Do
              Data = Temp
              Put #F, , Data
            Loop While LenB(Temp) = BLOCK_SIZE
          End Sub
    
          Sub WriteFromText(ByVal F As Long, fld As ADODB.Field, _
                            ByVal FieldSize As Long)
          Dim Data As String, CharsRead As Long
            Do While FieldSize <> CharsRead
              If FieldSize - CharsRead < BLOCK_SIZE Then
                Data = fld.GetChunk(FieldSize - BLOCK_SIZE)
                CharsRead = FieldSize
              Else
                Data = fld.GetChunk(BLOCK_SIZE)
                CharsRead = CharsRead + BLOCK_SIZE
              End If
              Put #F, , Data
            Loop
          End Sub
    
          Sub WriteFromUnsizedText(ByVal F As Long, fld As ADODB.Field)
          Dim Data As String, Temp As Variant
            Do
              Temp = fld.GetChunk(BLOCK_SIZE)
              If IsNull(Temp) Then Exit Do
              Data = Temp
              Put #F, , Data
            Loop While Len(Temp) = BLOCK_SIZE
          End Sub
    
          Sub FileToBlob(ByVal FName As String, fld As ADODB.Field, _
                         Optional Threshold As Long = 1048576)
          '
          ' Assumes file exists
          ' Assumes calling routine does the UPDATE
          ' File cannot exceed approx. 2Gb in size
          '
          Dim F As Long, Data() As Byte, FileSize As Long
            F = FreeFile
            Open FName For Binary As #F
            FileSize = LOF(F)
            Select Case fld.Type
              Case adLongVarBinary
                If FileSize > Threshold Then
                  ReadToBinary F, fld, FileSize
                Else
                  Data = InputB(FileSize, F)
                  fld.Value = Data
                End If
              Case adLongVarChar, adLongVarWChar
                If FileSize > Threshold Then
                  ReadToText F, fld, FileSize
                Else
                  fld.Value = Input(FileSize, F)
                End If
            End Select
            Close #F
          End Sub
    
          Sub ReadToBinary(ByVal F As Long, fld As ADODB.Field, _
                           ByVal FileSize As Long)
          Dim Data() As Byte, BytesRead As Long
            Do While FileSize <> BytesRead
              If FileSize - BytesRead < BLOCK_SIZE Then
                Data = InputB(FileSize - BytesRead, F)
                BytesRead = FileSize
              Else
                Data = InputB(BLOCK_SIZE, F)
                BytesRead = BytesRead + BLOCK_SIZE
              End If
              fld.AppendChunk Data
            Loop
          End Sub
    
          Sub ReadToText(ByVal F As Long, fld As ADODB.Field, _
                         ByVal FileSize As Long)
          Dim Data As String, CharsRead As Long
            Do While FileSize <> CharsRead
              If FileSize - CharsRead < BLOCK_SIZE Then
                Data = Input(FileSize - CharsRead, F)
                CharsRead = FileSize
              Else
                Data = Input(BLOCK_SIZE, F)
                CharsRead = CharsRead + BLOCK_SIZE
              End If
              fld.AppendChunk Data
            Loop
          End Sub
    					
  5. Menjalankan proyek dan klik tombol cmdSave.
  6. Dalam c: \ direktori, Anda harus menemukan berkas berikut: notes1.txt
    notes2.txt
    notes3.txt

    photo1.dat
    photo2.dat
    photo3.dat

    Tiga "foto" file harus ukuran yang sama dengan satu sama lain. Tiga "catatan" file harus ukuran yang sama dengan satu sama lain.

  7. Klik tombol cmdLoad.
  8. Buka database yang menggunakan akses dan Anda akan melihat enam tambahan karyawan dengan foto dan catatan dimuat kembali dengan benar.

Catatan

Berikut adalah beberapa saran untuk menggunakan BLOBs dengan ADO. Ini paralel banyak saran di artikel Basis Pengetahuan Microsoft berikut:
153238  (http://support.microsoft.com/kb/153238/EN-US/ ) Cara menggunakan GetChunk dan metode AppendChunk RDO objek
  1. Lebih efisien dari segi pengambilan data BLOB untuk hanya menyimpan data dalam file pada server dengan pointer dalam catatan utama (atau Anda dapat menggunakan beberapa jenis pemberian terstruktur direktori/nama file sistem berbasis pada nilai kunci primer). Ini memiliki keuntungan menghilangkan () Server overhead, (b) memungkinkan file yang akan disimpan di server kedua, (c) memungkinkan atribut keamanan jaringan diatur pada file individu, dan (d) memungkinkan pengambilan file bahkan ketika server sedang down. Ini terutama benar jika file semacam jenis dokumen, seperti bitmaps (.bmp), pengolah kata file (.doc), atau spreadsheet (.xls) di mana Anda dapat menunjukkan aplikasi host langsung ke file server.
  2. Ketika menggunakan penyedia tertentu, terutama ODBC SQL Server dan lainnya database, Anda mungkin harus berhati-hati dalam mengambil BLOB data, seperti menempatkan GUMPALAN kolom di akhir daftar bidang dan referensi semua bidang non-GUMPALAN sebelum akses GUMPALAN kolom. Ini akan tergantung pada beberapa faktor, seperti:
    • Penyedia (biasanya ODBC)
    • Back-end server
    • Kursor lokasi (biasanya klien)
    • Jenis kursor
    • Apakah Anda memilih dari pandangan atau mendapatkan catatan kembali dari prosedur yang tersimpan.
Karena hal ini tergantung pada berbagai faktor, di bawah ini adalah panduan jika Anda mengalami masalah dengan GUMPALAN kolom:
  • Mencoba penyedia OLE DB asli bukan penyedia ODBC.
  • Menggunakan Server-side kursor (seperti adOpenKeyset).
  • Pilih Primary Key column(s) Selain untuk kolom lain.
  • Pilih kolom GUMPALAN terakhir. Pilih setiap bidang, tidak "*".
  • Mengakses semua non-GUMPALAN kolom pertama (menyimpannya jika diperlukan).
  • Akses GUMPALAN kolom dalam urutan yang ditentukan. Anda mungkin hanya dapat referensi sekali sebelum kursor kehilangan nilainya.
  • Sewaktu mengedit kolom GUMPALAN yang menggunakan AppendChunk metode, yang mungkin Anda miliki untuk mengedit setidaknya satu non-GUMPALAN kolom dalam recordset Anda juga. Gumpalan biasanya tidak updateable dengan statis atau hanya maju kursor pada ODBC datasources.
  • Jika Anda menggunakan ODBC untuk Jet, Anda tidak dapat memperbarui recordset kembali oleh disimpan prosedur (QueryDef) sama sekali karena pengandar memaksa mereka untuk menjadi hanya-baca.
  • Microsoft Oracle OLE DB penyedia tidak saat ini mendukung acak Akses ke data BLOB dengan sisi server kursor - GUMPALAN kolom harus tampaknya akhir klausa pilih.
Dengan perpustakaan kursor ODBC, tidak mungkin untuk menggunakan GetChunk atau AppendChunk metode pada recordset kembali dari prosedur yang disimpan. Ini karena BLOB data tidak biasanya diperoleh dengan sisa data untuk menghemat bandwidth. Ketika prosedur yang disimpan menciptakan Recordset, pengandar kursor tidak bisa menentukan cara untuk query untuk GUMPALAN data setelah fakta karena tidak dapat menentukan basis tabel atau kunci Field untuk menggunakan. Server-side kursor mengurangi masalah ini tetapi membatasi Anda untuk pernyataan satu per disimpan prosedur (SQL Server pembatasan).

Fakta bahwa pengguna ingin memperbarui kolom GUMPALAN mereka menuntut bahwa mereka mengekspos meja dasar mereka dan membuat kursor dengan menggunakan standar pilih pernyataan dari meja dasar. Ini akan menjadi benar bahkan jika Anda coding langsung ke ODBC (bukan hal ADO).

REFERENSI

Untuk informasi tambahan, silakan lihat artikel berikut pada Basis Pengetahuan Microsoft:
185958  (http://support.microsoft.com/kb/185958/EN-US/ ) Bagaimana menggunakan ADO GetChunk/AppendChunk dengan Oracle untuk BLOB Data
189415  (http://support.microsoft.com/kb/189415/EN-US/ ) BERKAS: AdoChunk.exe menggunakan GetChunk dan AppendChunk di Visual C++
Menggunakan Data akses obyek:
103257  (http://support.microsoft.com/kb/103257/EN-US/ ) ACC: Membaca, menyimpan, & menulis ganda besar Objek (BLOBs)

Berlaku bagi:
  • Microsoft ActiveX Data Objects 2.7
  • Microsoft Visual Basic 6.0 Professional Edition
Kata kunci: 
kbbug kbdatabase kbhowto kbmt KB194975 KbMtid
Penerjemahan MesinPenerjemahan Mesin
PENTING: Artikel ini diterjemahkan menggunakan perangkat lunak mesin penerjemah Microsoft dan bukan oleh seorang penerjemah. Microsoft menawarkan artikel yang diterjemahkan oleh seorang penerjemah maupun artikel yang diterjemahkan menggunakan mesin sehingga Anda akan memiliki akses ke seluruh artikel baru yang diterbitkan di Pangkalan Pengetahuan (Knowledge Base) dalam bahasa yang Anda gunakan. Namun, artikel yang diterjemahkan menggunakan mesin tidak selalu sempurna. Artikel tersebut mungkin memiliki kesalahan kosa kata, sintaksis, atau tata bahasa, hampir sama seperti orang asing yang berbicara dalam bahasa Anda. Microsoft tidak bertanggung jawab terhadap akurasi, kesalahan atau kerusakan yang disebabkan karena kesalahan penerjemahan konten atau penggunaannya oleh para pelanggan. Microsoft juga sering memperbarui perangkat lunak mesin penerjemah.
Klik disini untuk melihat versi Inggris dari artikel ini:194975  (http://support.microsoft.com/kb/194975/en-us/ )