To read data, I used SqlDataReader which normally reads data one row at a time. The columns are buffered if available. Then you can access them by using the columns index. To access large object, we need to change this default behavior of DataReader to a sequential stream. This way you need to go through the bytes in the stream until the end of the stream is reached. Here is the code:
string constr = ConfigurationManager.ConnectionStrings["TestDBConnectionString"].ConnectionString;
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
long currentIndex = 0;
int byteCount;
using (SqlConnection conn = new SqlConnection(constr))
{
conn.Open();
using (SqlCommand comm = conn.CreateCommand())
{
comm.CommandText = "select TestID, TestTitle, TestData from TestTable where TestID=1000";
SqlDataReader reader = comm.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
string id = reader.GetInt64(0).ToString();
string title = reader.GetString(1);
using (FileStream fs = new FileStream(title + ".jpg",FileMode.Create,FileAccess.Write))
{
byteCount = (int)reader.GetBytes(2, currentIndex, buffer, 0, bufferSize);
while (byteCount!=0)
{
fs.Write(buffer, 0, byteCount);
currentIndex += byteCount;
byteCount = (int)reader.GetBytes(2, currentIndex, buffer, 0, bufferSize);
}
}
}
}
}
This code selects a row and retrieves the columns and cycles through the bytes of the third column (TestData) and writes it into a buffer of bytes and eventually writes the content of the buffer into a FileStream Object. The result is an image file in the file system.
To write the BLOB object, you need a pointer to the column that actually stores the data. So you first get the pointer by TEXTPTR T-SQL command. The returned scalar value is used to update the column with the stream of the actual data. There is a loop in the code below that does the main job. It reads an image file on the hard disk and buffers its content and writes the buffer into the column on each iteration of the loop until the end of the file has been reached. Note that you have to provide a few paramters for the T-SQL that updates the column. A parameter holds the current index of data written into the column (offsetParam), one is the pointer that indicates the column to be updated (pointerParam) and is retreieved at the beginning of the code. The last one is the parameter that keep the actual data (dataParam).
string constr = ConfigurationManager.ConnectionStrings["TestDBConnectionString"].ConnectionString;
int bufferSize = 100;
byte[] buffer = new byte[bufferSize];
long currentIndex = 0;
byte[] dataPtr;
using (SqlConnection conn = new SqlConnection(constr))
{
conn.Open();
using (SqlCommand comm = conn.CreateCommand())
{
comm.CommandText = "select textptr(TestData) from TestTable where TestID=1000";
dataPtr = (byte[])comm.ExecuteScalar();
}
using (SqlCommand comm2 = conn.CreateCommand())
{
comm2.CommandText = "updatetext TestTable.TestData @pointer @offset null @data";
SqlParameter pointerParam = comm2.Parameters.Add("@pointer", SqlDbType.Binary, 16);
pointerParam.Value = dataPtr;
SqlParameter dataParam = comm2.Parameters.Add("@data", SqlDbType.Image);
SqlParameter offsetParam = comm2.Parameters.Add("@offset", SqlDbType.Int);
offsetParam.Value = 0;
using (FileStream fs = new FileStream("C:\\image.jpg", FileMode.Open, FileAccess.Read))
{
int count = fs.Read(buffer, 0, bufferSize);
while (count != 0)
{
dataParam.Value = buffer;
dataParam.Size = count;
comm2.ExecuteNonQuery();
currentIndex += count;
offsetParam.Value = currentIndex;
count = fs.Read(buffer, 0, bufferSize);
}
}
}
}
No comments:
Post a Comment