Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.
Para uma versão deste artigo do Microsoft Visual Basic. NET, consulte 317034
(http://support.microsoft.com/kb/317034/EN-US/
)
.
Para uma versão deste artigo do Microsoft Visual Basic. NET, consulte 316887
(http://support.microsoft.com/kb/316887/EN-US/
)
.
Este artigo descreve como ler e gravar Binary Large Objects (BLOBs) usando métodos AppendChunk e GetChunk contra campos em ADO. Ele também inclui código de exemplo usando o banco de dados de exemplo NWIND.
Os métodos AppendChunk e GetChunk trabalham com os tipos de coluna LongVarChar, LongVarWChar e LongVarBinary, também conhecido como TEXT, NTEXT e IMAGE colunas, no Microsoft SQL Server e como campos de MEMO e OLE em bancos de dados Microsoft Jet. Você pode identificar essas colunas no ADO testando a propriedade Type de um campo para os valores adLongVarChar, adLongVarWChar e adLongVarBinary. Você também pode testar a propriedade Attributes de um campo para o sinalizador adFldLong:
If fld.Attributes And adFldLong Then
' You can use GetChunk/AppendChunk
longo de colunas são normalmente conhecidas como BLOBs (grandes objetos binários) mesmo que eles podem conter dados de texto. O código de exemplo abaixo fornece duas rotinas, BlobToFile e FileToBlob.
BlobToFile determina o tipo de dados do campo e qual dos três métodos para usar para gravar os dados BLOB em um arquivo de disco. Se os dados BLOB forem pequenos o suficiente ele irá fazer referência o valor do campo em sua totalidade sem chamar GetChunk. Se o tamanho do BLOB for desconhecido, ele irá chamar WriteFromUnsizedBinary ou WriteFromUnsizedText para gravar os dados. Isso é menos eficiente em termos de fazer cópias extras dos dados na memória local que as rotinas de WriteFromBinary e WriteFromText são usadas quando o tamanho dos dados BLOB é conhecido:
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 determina se deve usar AppendChunk ou atribuir diretamente os dados para o campo BLOB com base no tamanho do arquivo. Como sempre é possível determinar o tamanho do arquivo, não há nenhum rotinas "Unsized" pois há no código de exemplo 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
O código de exemplo para BlobToFile e FileToBlob é armazenado em um módulo, enquanto o código de teste está por trás do formulário padrão. O código de teste usa cada um dos três métodos para salvar a foto (IMAGE/OLE/LongVarBinary) de disco e observações (texto/MEMO/LongVarChar/LongVarWChar) campos para Carina Fuller da tabela Funcionários do banco de dados NWIND. -La e lê os arquivos de volta e cria novos seis registros, cada um dos três conjuntos de arquivos por meio de dois diferentes métodos de leitura de leitura. Observação : usando ADO 2.1 ou posterior, você pode ver o seguinte erro na linha de código:
Data = fld.GetChunk(BLOCK_SIZE) :
Run-time error '94':
Invalid use of Null
ADO 2.1 ou posterior pode relatar a propriedade ActualSize de um campo BLOB de tipo de texto como duas vezes o número de caracteres. Isso é correto se o campo BLOB contiver texto em Unicode, porque Unicode usa 2 bytes por caractere. Isso é incorreto se o campo BLOB contiver texto ANSI, que usa 1 byte por caractere. Se o ActualSize é duas vezes o comprimento de um campo de ANSI, em seguida, GetChunk eventualmente tentará obter após o final do campo.
Você pode ver esse comportamento nas seguintes situações e pode vê-lo em outros cenários:
cenário 1 :
Com um campo do SQL Server 7 NTEXT (texto de ANSI), usar tanto o provedor OLE DB para SQL Server ou o provedor ODBC com o driver ODBC para SQL Server.
Observe que usando o SQL Server texto (Unicode) do campo funciona com os dois provedores.
cenário 2 :
Com campos de MEMO do Access 97 e Access 2000 MEMO campos com ou sem compactação Unicode, usando tanto o provedor OLEDB para o Jet 4.0 ou o provedor ODBC com o driver ODBC Jet 4.0, ODBCJT32.DLL.
Observe que, com campos do Access 97 MEMO, ambos os o OLE DB Provider for Jet 3.51 e o provedor ODBC com o trabalho de driver Jet ODBC 3.51 corretamente.
Existem diversas soluções possíveis para erro de tempo de execução '94':
Usar rs.fieldname.ActualSize \ 2 em vez de rs.fieldname.ActualSize. Isso resolve dos cenários específicos listados acima.
Use o método 2 ou 3 abaixo, nenhum dos quais dependem da propriedade ActualSize.
Criar um novo projeto Visual Basic e a partir do menu Project, selecione References e selecione Microsoft ActiveX Data Objects Library ou Microsoft ActiveX Data Objects Library.
Adicione dois CommandButtons (cmdSave e cmdLoad) form(Form1) padrão.
Adicione o seguinte código. Você precisará alterar a seqüência de conexão fornecida na linha "cn.Open":
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
Adicionar um novo módulo ao projeto (Module1) com o código a seguir:
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
Executar o projeto e clique no botão cmdSave.
No diretório C:\, você deve encontrar os seguintes arquivos: notes1.txt notes2.txt notes3.txt
photo1.dat photo2.dat photo3.dat
Os três arquivos "foto" devem ser do mesmo tamanho que uns aos outros. Os três arquivos "anotações" devem ser do mesmo tamanho que uns aos outros.
Clique no botão cmdLoad.
Abrir o banco de dados usando acesso e você deve ver seis funcionários adicionais com fotos e anotações volta carregadas corretamente.
A seguir está algumas sugestões para usar BLOBs com ADO. Esses paralela muitas das sugestões no seguinte artigo da Base de dados de Conhecimento Microsoft:
153238
(http://support.microsoft.com/kb/153238/EN-US/
)
Como usar métodos AppendChunk do objeto RDO e GetChunk
É mais eficiente em termos de recuperação de dados BLOB para simplesmente armazenar os dados em arquivos no servidor com um ponteiro de registro principal (ou você pode usar algum tipo de diretório/arquivo estruturado nomeação sistema com base no valor da chave primária). Isso tem a vantagem do (a) eliminando a sobrecarga do servidor, (b) permitindo que os arquivos a ser armazenado em um segundo servidor, (c) permitindo rede atributos de segurança a ser definida em arquivos individuais e (d) permitindo recuperação de arquivos, mesmo quando o servidor está desativado. Isso é especialmente verdadeiro se os arquivos estiverem algum tipo de tipo de documento, como bitmaps (.bmp), arquivos de processador (.doc) ou planilhas (.xls) onde você pode apontar o aplicativo host diretamente para o arquivo no servidor.
Ao usar determinados provedores, mais notavelmente ODBC para SQL Server e outros bancos de dados, talvez você precise Tome um cuidado especial em recuperar dados BLOB, como colocar colunas BLOB no final da lista de campos e fazendo referência a todos os campos não-BLOB antes para colunas BLOB de acesso. Isso dependerá de vários fatores, como:
Provedor (normalmente ODBC)
Servidor back-end
Cursor local (normalmente cliente)
Tipo de cursor
Se você estiver selecionando uma visualização ou obtendo os registros retornados de um procedimento armazenado.
Porque isso depende de diversos fatores, abaixo é um guia se você estiver tendo problemas com colunas BLOB:
Tente um provedor OLE DB nativo em vez de um provedor ODBC.
Use cursores do lado do servidor (como adOpenKeyset).
Selecione as colunas de chave primária com as outras colunas.
Selecione as colunas BLOB pela última vez. Selecione campos individuais, não "*".
Acessar todas as colunas não-BLOB primeiro (armazená-los se necessário).
Colunas BLOB acesso na ordem especificada. Você somente poderá referência a ele vez antes do cursor perde seu valor.
Ao editar uma coluna BLOB usando o método AppendChunk, talvez você precise editar pelo menos uma coluna BLOB não no seu conjunto de registros. BLOBs geralmente não são atualizáveis com cursores somente direta no ODBC datasources ou estático.
Se você usar ODBC Jet, você não pode atualizar um conjunto de registros retornado por um procedimentos armazenados (QueryDef) em todos os porque o driver obriga a ser somente leitura.
O Oracle provedor Microsoft OLE DB não oferece atualmente suporte aleatório acesso a dados BLOB com cursores server-side - coluna BLOB deve aparecer para o final da cláusula SELECT.
Com a biblioteca de cursor ODBC, não é possível usar os métodos AppendChunk ou GetChunk em um conjunto de registros retornado de um procedimento armazenado. Isso ocorre porque os BLOB dados não é normalmente recuperados com o restante dos dados para economizar largura de banda. Quando um procedimento armazenado cria um conjunto de registros, o driver de cursor não pode determinar como consultar os dados BLOB após o fato porque ele não é possível determinar as tabelas base ou campos de chave para usar. Cursores server-side aliviar esse problema, mas limitam você a uma única instrução por procedimento armazenado (uma restrição do SQL Server).
O fato de que os usuários desejam atualizar sua coluna BLOB exige que expõem suas tabelas de base e criar o cursor usando uma instrução select padrão dessa tabela base. Isso seria verdadeiro mesmo se você foram codificando diretamente ao ODBC (não uma coisa ADO).
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 194975
(http://support.microsoft.com/kb/194975/en-us/
)
Quanto esforço foi necessário para seguir os procedimentos deste artigo?
Muito baixo
Baixo
Moderado
Alto
Muito alto
Diga-nos o porque e o que podemos fazer para melhorar esta informação
Obrigado! Seus comentários são usados para nos ajudar a aperfeiçoar o conteúdo de suporte. Para obter mais opções de ajuda, visite a Home Page de Ajuda e Suporte.