I am currently banging my head against the wall and it is starting to hurt, I am trying to store images used in a windows application within a .mdb database. Within the table of the database the field in question is set to OLE Object.
The method I am using to put the image into the database is as follows:
public static bool UpdateContractor(Utils.Contractor cnt)
{
if(! DataManager.bReady) throw new DataManagerNotReadyException("The local database is not ready");
//serialise the image
MemoryStream memStream1 = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memStream1,cnt.bmpLogo);
byte [] bytes = memStream1.GetBuffer();
memStream1.Close();
//this is variable as would be expected, it varies with the image
System.Windows.Forms.MessageBox.Show(bytes.Length.ToString());
OleDbCommand aCommand = new OleDbCommand("UPDATE [Contractors] SET [Contact] = '" +
cnt.strContact + "'," +
"[Location] = '" + cnt.strLocation + "'," +
"[Town] = '" + cnt.strTown +"'," +
"[State] = '" + cnt.strState + "'," +
"[Zip] = '" + cnt.strZip + "'," +
"[Tel] = '" + cnt.strTel + "'," +
"[Mobile] = '" + cnt.strMobile + "'," +
"[Email] = '" + cnt.strEmail + "'," +
"[Fax] = '" + cnt.strFax + "'," +
"[Logo] = '" + bytes + "' WHERE [Id] = '" + cnt.nIndex + "'" , DataManager.dbLocal);
bool bResult = false;
try
{
DataManager.dbLocal.Open();
if(aCommand.ExecuteNonQuery() > 0)
{
bResult = true;
}
}
catch(Exception ex)
{
throw new DataAccessException(ex.Message);
}
finally
{
DataManager.dbLocal.Close();
}
return bResult;
}
cnt.BmpLogo is a Bitmap object.
The object appears in the mdb as expected, but I am having trouble getting it back out.
The code I am using to get the image back into the application is as follows:
object obj = aReader.GetValue(11);
MemoryStream memStream1 = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memStream1,obj);
byte [] bytes = memStream1.GetBuffer();
//the result of this is always 256 even if the the image field is empty
System.Windows.Forms.MessageBox.Show(bytes.Length.ToString());
memStream1.Close();
MemoryStream memStream2 = new MemoryStream(bytes);
//this throws a cast exception
cnt.bmpLogo = (System.Drawing.Bitmap)formatter.Deserialize(memStream2);
memStream2.Close();
aReader.GetValue(11) is the correct field.
The size of the contrcuted byte array is always 256, even if the field does not contain an image, also this field is never dbNull, even if it , well is.
If anyone can offer a hint as to what I am doing wrong I would be very appreciative. Perhaps I have been at it to long
I am using vs 2003.
Thanks.
Gav

C# - OleDb - Access(MDB) : storing and retrieving images
rgrid
As Matt says, and dont forget to use parameters with your database connection
Just a note.
I dont belive you need to serialize to file, so you could streamline the process by doing something like :
(in) - bytes is the resultant value to be placed in access as 'OleDbType.LongVarBinary'
MemoryStream memStream1 = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memStream1,MyObject);
byte [] bytes = memStream1.GetBuffer(); //you could use the result of this method directly
memStream1.Close();
(out)
MemoryStream memStream1 = new MemoryStream((byte[])aReader.GetValue(0)); //change to your relevance
BinaryFormatter formatter = new BinaryFormatter();
obj = (MyClass)formatter.Deserialize(memStream1);
memStream1.Close();
Regards
Gav
SNOMan
Thanks.. that is a good idea...., may I add, encrypting the file for security
...about overhead performance..., for instance if I had a student who wanted to review all his past exams which could be around 60+.. which way would be faster, reading and loading from access or disk
Rits
Well you would have to serialize the structure to some format. In C# you could use the binary serialization support, just add Serializable attribute to your class like so:
[Serializable] public class MyObject { public int n1 = 0; public int n2 = 0; public String str = null; }Giv Afshar
Steven D
You need to use a parameterized OleDbCommand. Inlining the SQL will not work here.
So see for example this code ->
http://www.atalasoft.com/products/dotimage/docs/Database.html
[C#]
OleDbConnection myConnection = null;
try
{
//save image to byte array and allocate enough memory for the image
byte[] imagedata = image.ToByteArray(new Atalasoft.Imaging.Codec.JpegEncoder(75));
//create the SQL statement to add the image data
myConnection = new OleDbConnection(CONNECTION_STRING);
OleDbCommand myCommand = new OleDbCommand("INSERT INTO Atalasoft_Image_Database (Caption, ImageData) VALUES ('" + txtCaption.Text + "', )", myConnection);
OleDbParameter myParameter = new OleDbParameter("@Image", OleDbType.LongVarBinary, imagedata.Length);
myParameter.Value = imagedata;
myCommand.Parameters.Add(myParameter);
//open the connection and execture the statement
myConnection.Open();
myCommand.ExecuteNonQuery();
}
finally
{
myConnection.Close();
}
Zephyr12345
In general the ability to store images inside Access db is just a convenience factor. It allows you to store everything in one file. If you wanted you could create your own file format and store a bunch of images in the same file, right Or you could store the images in a zip archive for example. There is no big difference. The key thing is Access db has a 2 GB limit in size, so this could be a limiting factor. Also, if the Access db becomes corrupt, there is no easy way to recover the images.
So the key feature is the images are all stored in one file. If you like this feature then use it, if this feature is not as important, don't use it.
Wingnut_233
C# 2005
How do you store objects into a Access.mdb. I want to take a struct with different types variables and constants and store it in the .mdb.
I know my .mdb variable type has to be OLE Object. All I need is an example how to store and retreave it.
Also can my struct have an CollectList and be store in the .mdb with no problems
Thanks for you help!...
santaclause585
Works a treat.
I was being a bit silly really
Gav
Tamilmannan
Thanks for the helpful info on this thread. In case anyone else comes by and wants to see a complete example. Here it is:
public class ChapterExam
{
public ExamConfigData m_ExamData;
public ChapterExam()
{
m_ExamData = new ExamConfigData();
m_ExamData.m_MarkBooks = new System.Collections.ArrayList();
System.Data.OleDb.OleDbCommand dbCmd1;
System.Data.OleDb.OleDbDataReader dbReader;
dbCmd1 = new System.Data.OleDb.OleDbCommand();
dbCmd1.Connection = AccessDatabase.GetDbConnection();
dbCmd1.CommandText =
String.Format("SELECT * FROM {0}
WHERE (ExamKey = 'T1B10C1' AND ExamNo = 367 AND ExamName = 'History')",
ReferenceExamsConst.COMPLETEEXAMS);
dbReader = dbCmd1.ExecuteReader();
if (dbReader.HasRows)
{
dbReader.Close();
OpenBooksExaminations(dbReader, dbCmd1);
}
else
{
dbReader.Close();
CreateBooksExaminations(dbCmd1);
}
}
void OpenBooksExaminations(System.Data.OleDb.OleDbDataReader dbReader,
System.Data.OleDb.OleDbCommand dbCmd)
{
byte[] ClassObjArray;
MemoryStream memStream;
BinaryFormatter formatter;
dbCmd.CommandText =
String.Format("SELECT ClassObj FROM {0}
WHERE (ExamKey = 'T1B10C1' AND ExamNo = 367 AND ExamName = 'History')",
ReferenceExamsConst.COMPLETEEXAMS);
ClassObjArray = (byte[]) dbCmd.ExecuteScalar();
if (ClassObjArray != null)
{
memStream = new MemoryStream(ClassObjArray);
formatter = new BinaryFormatter();
m_ExamData = (ExamConfigData) formatter.Deserialize(memStream);
memStream.Close();
}
}
void CreateBooksExaminations(System.Data.OleDb.OleDbCommand dbCmdSave)
{
System.Data.OleDb.OleDbCommand dbCmdExams;
System.Data.OleDb.OleDbDataReader dbReaderExams;
System.Data.OleDb.OleDbParameter parameter;
byte[] ClassObjArray;
MemoryStream memStream;
BinaryFormatter formatter;
dbCmdExams = new System.Data.OleDb.OleDbCommand();
dbCmdExams.Connection = AccessDatabase.GetDbConnection();
dbCmdExams.CommandText = String.Format("SELECT * FROM {0}
WHERE (Book = 'ExamBook') ORDER BY SortKey", ReferenceExamsConst.EXAMS);
dbReaderExams = dbCmdExams.ExecuteReader();
if (!dbReaderExams.HasRows) return;
while (dbReaderExams.Read())
{
m_ExamData.m_MarkBooks.Add(dbReaderExams["Exam"].ToString());
System.Console.WriteLine("{0}", dbReaderExams["Exam"].ToString());
}
memStream = new MemoryStream();
formatter = new BinaryFormatter();
formatter.Serialize(memStream, m_ExamData);
ClassObjArray = memStream.GetBuffer();
memStream.Close();
dbCmdSave.CommandText = String.Format("INSERT INTO {0} (ExamKey, ExamNo,
ExamName, ClassObj) VALUES ('T1B10C1', 367, 'History', )",
ReferenceExamsConst.COMPLETEEXAMS);
parameter = new
OleDbParameter("@ClassObj", OleDbType.LongVarBinary, ClassObjArray.Length);
parameter.Value = ClassObjArray;
dbCmdSave.Parameters.Add(parameter);
dbCmdSave.ExecuteNonQuery();
}
}