Inserting smaller images work fine. However, when the image file gets bigger than about 2MB, I get an OutOfMemoryException
.
I tried with SqlCeUpdatableRecord
and a parameterized SqlCeCommand
. Using the SqlCeCommand
, the exception is raised at ExecuteNonQuery()
.
With SqlCeUpdatableRecord
, the exception is raised at SqlCeUpdatableRecord.SetBytes()
.
I’ve tried increasing buffer size and temp file size without it seeming to have an effect. I've debugged with GetTotalMemory
and there seems to be plenty of resources available.
Any tips would be highly appreciated.
The SQL Server CE database is synchronized with a main SQL Server database and handling images as separate files would introduce a truckload of other issues. The solution has worked fine for years as most WM handhelds only capture images at 5MP or less. However, newer models with support for 8MP images is causing issues.
Here is a simplified version of the SqlCeUpdateblRecord
implementation:
System.Data.SqlServerCe.SqlCeUpdatableRecord newRecord = base.CreateRecord();
newRecord["ImageId"] = ImageId;
newRecord["ImageType"] = ImageType;
//64kb buffer (Have tested with different buffer sizes (up to 8MB)
newRecord.SetBytesFromFile("ImageFull", ImageFullFileName, 65536);
newRecord["ImageThumb"] = ImageThumb;
newRecord["ImageDate"] = ImageDate;
base.Insert(newRecord);
.....
public static void SetBytesFromFile(this SqlCeUpdatableRecord obj, string name, string filename, int buffersize)
{
int _column = obj.GetOrdinal(name);
byte[] buffer = new byte[buffersize];
int bytesread;
long offset = 0;
using (FileStream fs = new FileStream(filename,FileMode.Open))
{
bytesread = fs.Read(buffer, 0, buffersize);
while (bytesread > 0)
{
//This will raise OutOfMemoryException for imagefiles larger than appx. 2mb, regardless of buffersize
obj.SetBytes(_column, offset, buffer, 0, bytesread);
offset = offset + (long)bytesread;
bytesread = fs.Read(buffer, 0, buffersize);
}
}
}
Here is a simplified version of the paramterized query:
using (var cmdInsert = new SqlCeCommand("INSERT INTO [Image_CF] ( [ImageId], [ImageType], [ImageFull], [ImageThumb], [ImageDate]) VALUES " +
" ( @ImageId, @ImageType, @ImageFull, @ImageThumb, @ImageDate)"))
{
cmdInsert.Connection = Database.IrisPdaConnection;
cmdInsert.Parameters.Add("@ImageId", System.Data.SqlDbType.Int).Value = ImageId;
cmdInsert.Parameters.Add("@ImageType", System.Data.SqlDbType.NVarChar).Value = ImageType;
cmdInsert.Parameters.Add("@ImageFull", System.Data.SqlDbType.Image).Value = GetFileAsBytes(ImageFullFileName);
cmdInsert.Parameters.Add("@ImageThumb", System.Data.SqlDbType.Image).Value = ImageThumb;
cmdInsert.Parameters.Add("@ImageDate", System.Data.SqlDbType.NVarChar).Value = ImageDate;
// OutOfMemoryException for images larger than appx. 2MB
cmdInsert.ExecuteNonQuery();
}
public byte[] GetFileAsBytes(string filename)
{
FileStream fs;
byte[] result;
using (fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
// a byte array to read the image
result = new byte[fs.Length];
fs.Read(result, 0, System.Convert.ToInt32(fs.Length));
}
return result;
}