Almacenar una imagen en un campo Adjunto en una base de datos de Access

Estoy escribiendo una aplicación VB donde necesito almacenar una imagen en la base de datos. El usuario selecciona la imagen en su computadora, lo que me da la ruta como una cadena. Este es mi bash, sin embargo recibo el error “Una consulta INSERT INTO no puede contener un campo multivaluado”.

Aquí está mi código:

Dim buff As Byte() = Nothing Public Function ReadByteArrayFromFile(ByVal fileName As String) As Byte() Dim fs As New FileStream(fileName, FileMode.Open, FileAccess.Read) Dim br As New BinaryReader(fs) Dim numBytes As Long = New FileInfo(fileName).Length buff = br.ReadBytes(CInt(numBytes)) Return buff End Function Sub .... Dim connImg As New OleDbConnection Dim sConnString As String Dim cmdImg As New OleDbCommand sConnString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & My.Settings.DB & ";Persist Security Info=False;" connImg = New OleDbConnection(sConnString) connImg.Open() cmdImg.Connection = connImg cmdImg.CommandType = CommandType.Text If d.slogo  "" Then cmdImg.CommandText = "INSERT INTO Logo ( refId, [type], [img] ) VALUES(@refId, @type, @imgBinary)" cmdImg.Parameters.Add("@refId", OleDbType.Double).Value = refId cmdImg.Parameters.Add("@type", OleDbType.Double).Value = 0 cmdImg.Parameters.Add("@imgBinary", OleDbType.VarBinary).Value = ReadByteArrayFromFile(PathToImage) cmdImg.ExecuteNonQuery() End If .... End Sub 

Intenté buscar otras soluciones en línea, pero parece que todo lo que encuentro es código VB6 o VBA. Y sé que la gente va a argumentar que las imágenes no deberían almacenarse en la base de datos, pero en este caso, es mi única opción.

¡Gracias por cualquier ayuda!

Como ha descubierto, no puede usar una statement de SQL para insertar archivos en un campo Attachment en una base de datos de Access. LoadFromFile() utilizar el método LoadFromFile() de un objeto ACE DAO Field2 . El siguiente código C # funciona para mí. Se adapta desde la entrada del Blog de Office aquí .

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Office.Interop.Access.Dao; namespace daoConsoleApp { class Program { static void Main(string[] args) { // This code requires the following COM reference in your project: // // Microsoft Office 14.0 Access Database Engine Object Library // var dbe = new DBEngine(); Database db = dbe.OpenDatabase(@"C:\__tmp\testData.accdb"); try { Recordset rstMain = db.OpenRecordset( "SELECT refId, img FROM Logo WHERE refId = 1", RecordsetTypeEnum.dbOpenDynaset); if (rstMain.EOF) { // record does not already exist in [Logo] table, so add it rstMain.AddNew(); rstMain.Fields["refId"].Value = 1; } else { rstMain.Edit(); } // retrieve Recordset2 object for (potentially multi-valued) [img] field // of the current record in rstMain Recordset2 rstAttach = rstMain.Fields["img"].Value; rstAttach.AddNew(); Field2 fldAttach = (Field2)rstAttach.Fields["FileData"]; fldAttach.LoadFromFile(@"C:\__tmp\testImage.jpg"); rstAttach.Update(); rstAttach.Close(); rstMain.Update(); rstMain.Close(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } } 

Hice lo mismo basado en el código anterior y en la entrada del blog desde aquí .

Aquí está mi código de vb.net que me permite hacer un OpenFileDialog y múltiples selecciones y la función manejará el almacenamiento de múltiples archivos sin problemas. Aunque tuve que agregar una referencia a mi proyecto para Microsoft Office 15.0 Acceder a la biblioteca de objetos del motor de la base de datos para que funcione correctamente. Creo que también puedes bajar a 12.0 o 14.0.

 Private Sub AddAttachment(ByVal Files() As String) Const Caller = "AddAttachment" Dim dbe = New Microsoft.Office.Interop.Access.Dao.DBEngine() Dim db As Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(dbPath) Try Dim rstMain As Microsoft.Office.Interop.Access.Dao.Recordset rstMain = db.OpenRecordset("SELECT ID, fieldName FROM tableName WHERE ID = " + (dt.Rows(currentRow).Item("ID").ToString), Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenDynaset) If (rstMain.EOF) Then rstMain.AddNew() rstMain.Fields("ID").Value = 1 Else For Each value As String In Files rstMain.Edit() Dim rstAttach As Microsoft.Office.Interop.Access.Dao.Recordset2 rstAttach = rstMain.Fields("ATTACHMENTS").Value rstAttach.AddNew() Dim fldAttach As Microsoft.Office.Interop.Access.Dao.Field2 fldAttach = rstAttach.Fields("FileData") fldAttach.LoadFromFile(value) rstAttach.Update() rstAttach.Close() Next rstMain.Update() rstMain.Close() End If Catch ex As Exception If Err.Number <> 3820 Then MsgBox(ex.Message) Else MsgBox("File of same name already attached", MsgBoxStyle.Critical, "Cannot attach file" & Caller) MessageBox.Show(ex.Message) End If End Try End Sub 

Ahora estoy trabajando en las funciones para Eliminar Adjuntos y guardo archivos del campo de adjuntos. Los publicaré aquí más tarde.

Otra cosa para agregar a esto. Si su base de datos está encriptada, entonces deberá agregarla al comando OpenDatabase.

Este es el código que utilicé en C # pero el código de VB.NET será muy similar. db = dbe.OpenDatabase (dbPath, falso, falso, “MS Access; PWD = contraseña”);

Me tomó años tratar de rastrear esto por mi cuenta y trataré de analizar las diversas partes del método. El artículo de MSDN para él se puede encontrar aquí .

1er argumento: dbPath, es lo mismo que el uso en la publicación original. La ubicación y el nombre de archivo de la base de datos que desea abrir.

Segundo argumento: falso. Este es un argumento verdadero / falso que si es verdadero abre la base de datos en modo exclusivo. Para que solo este único progtwig pueda usarlo. La mayoría de las veces esto debería ser falso. Solo use el modo exclusivo si es necesario.

Tercer argumento: falso. Este es otro argumento verdadero / falso. Esta vez, si es cierto, abre la base de datos en modo de solo lectura. Esto significa que solo puede usar conjuntos de registros para leer información y no puede usar los métodos Editar, Agregar o Eliminar. Esto puede ser verdadero o falso dependiendo de sus necesidades.

4to argumento: Establece propiedades específicas sobre cómo abrir la base de datos. En este caso. Dice establecer la propiedad de Microsoft Access ‘PWD’ en ‘contraseña’. En esta propiedad, la configuración le indicará al método que abra una base de datos cifrada usando la contraseña ‘contraseña’. Por supuesto, tendrá que cambiar la “contraseña” a lo que sea que se abra la contraseña real de la base de datos, pero he estado buscando esto por un tiempo.

Espero que esto ayude.

    Intereting Posts