Read Write BLOBs From To SQL Server Using C#
Read Write BLOBs From To SQL Server Using C#
NET
DataReader
More Information on installing the .Net Framework click here.
Download full Visual Studio C# .NET Examples from this Article.
The default behavior of the DataReader is to load incoming data as a row as soon as an entire row of data
Binary large objects (BLOBs) need to be treated differently, however, because they can contain gigabytes o
be contained in a single row. The Command.ExecuteReader method has an overload which will take
a CommandBehavior argument to modify the default behavior of the DataReader. You can
pass CommandBehavior.SequentialAccess to the ExecuteReader method to modify the default behavior
so that instead of loading rows of data, it will load data sequentially as it is received. This is ideal for loadin
large data structures. Note that this behavior may differ depending on your data source.
SequentialAccess
Provides a way for the DataReader to handle rows that contain columns with large binary values BLOB
loading the entire row, SequentialAccess enables the DataReader to load data as a stream. When setting t
use SequentialAccess, it is important to note the sequence in which you access the fields returned.
behavior of the DataReader, which loads an entire row as soon as it is available, allows you to access the fi
any order until the next row is read. When using SequentialAccess however, you must access the di
returned by the DataReader in order. For example, if your query returns three columns, the third of wh
must return the values of the first and second fields before accessing the BLOB data in the third field. If you
field before the first or second fields, the first and second field values will no longer be available. This is bec
SequentialAccess has modified the DataReader to return data in sequence and the data will not be available
DataReader has read past it.
When accessing the data in the BLOB field, use the GetBytes or GetChars typed accessors of the Da
an array with data. You can also use GetString for character data, however to conserve system resources y
to load an entire BLOB value into a single string variable. You can specify a specific buffer size of data to be
starting location for the first byte or character to be read from the returned data. GetBytes and GetChars w
value, which represents the number of bytes or characters returned. If you pass a null array to Get
the long value returned will be the total number of bytes or characters in the BLOB. You can optionally spec
array as a starting position for the data being read.
You can write a binary large object (BLOB) to a database as either binary or character data, depending on t
your data source. To write a BLOB value to your database, issue the appropriate INSERT or UPDATE statem
BLOB value as an input parameter. If your BLOB is stored as text, such as a SQL Server text field, you can
a string parameter. If the BLOB is stored in binary format, such as a SQL Server image field, you c
of type byte as a binary parameter.
Example
The following code example adds employee information to the Employees table in the Northwind databas
employee is read from a file and added to the Photo field in the table, which is an image field. The Photo f
using GetBytes. Notice that the employee id is accessed for the current row of data before the Photo, beca
be accessed sequentially.
using
using
using
using
using
System;
System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
using System.IO;
namespace Akadia.ReadWriteBlob
{
// Read and Write BLOB to/from Filesystem and Database
public class BlobSample : System.Windows.Forms.Form
{
private System.Windows.Forms.PictureBox pbxPhoto;
private System.ComponentModel.Container components = null;
private System.Windows.Forms.Button btnLoadPhoto;
private System.Windows.Forms.Button btnAddEmp;
private System.Windows.Forms.Button btnGetEmp;
private System.Windows.Forms.StatusBar statusBar;
// My own private Variables
private String _fname = null;
private SqlConnection _conn;
// Constructor
public BlobSample()
{
// Initialize GUI
InitializeComponent();
// Get Database Connection
_conn = new SqlConnection("data source=XEON;"+
"initial catalog=Northwind;"+
"user id=sa;password=manager;");
}
// **** Read Image from Filesystem and add it to the Database.
public void AddEmployee(
string plastName,
string pfirstName,
string ptitle,
DateTime phireDate,
int preportsTo,
string photoFilePath)
{
// Read Image into Byte Array from Filesystem
byte[] photo = GetPhoto(photoFilePath);
// Construct INSERT Command
SqlCommand addEmp = new SqlCommand(
"INSERT INTO Employees ("+
"LastName,FirstName,Title,HireDate,ReportsTo,Photo) "+
"VALUES(@LastName,@FirstName,@Title,@HireDate,@ReportsTo,@Photo)",_conn);
addEmp.Parameters.Add("@LastName",
addEmp.Parameters.Add("@FirstName",
addEmp.Parameters.Add("@Title",
addEmp.Parameters.Add("@HireDate",
addEmp.Parameters.Add("@ReportsTo",
addEmp.Parameters.Add("@Photo",
// Open the Connection and INSERT the BLOB into the Database
_conn.Open();
addEmp.ExecuteNonQuery();
_conn.Close();
}
// **** Read Image into Byte Array from Filesystem
public static byte[] GetPhoto(string filePath)
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] photo = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
return photo;
}
// **** Read BLOB from the Database and save it on the Filesystem
public void GetEmployee(string plastName,string pfirstName)
{
SqlCommand getEmp = new SqlCommand(
"SELECT EmployeeID, Photo "+
"FROM Employees "+
"WHERE LastName = @lastName "+
"AND FirstName = @firstName", _conn);
//
//
//
//
//
//
//
// Read the bytes into outbyte[] and retain the number of bytes returned.
retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);
// Continue reading and writing while there are bytes beyond the size of t
while (retval == bufferSize)
{
bw.Write(outbyte);
bw.Flush();
// Reposition the start index to the end of the last buffer and fill t
startIndex += bufferSize;
retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);
}
// Write the remaining buffer.
bw.Write(outbyte, 0, (int)retval);
bw.Flush();
// Close the output file.
bw.Close();
fs.Close();
}
// Close the reader and the connection.
myReader.Close();
_conn.Close();
}
private void btnAddEmp_Click(object sender, System.EventArgs e)
{
DateTime hireDate = DateTime.Parse("2003.05.03");
AddEmployee("Mary","Jones","Software Engineer",hireDate,5,_fname);
statusBar.Text = "Employee added to the Database";
}
private void btnGetEmp_Click(object sender, System.EventArgs e)
{
GetEmployee("Mary","Jones");
statusBar.Text = "Employee saved to Filesystem";
}
private void btnLoadPhoto_Click(object sender, System.EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Open Photo";
dlg.Filter = "Windows Bitmap Files (*.bmp)|*.bmp"
+ "|All files (*.*)|*.*";
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
pbxPhoto.Image = new Bitmap(dlg.OpenFile());
_fname = dlg.FileName;
}