How to: Work with Data Streams
An entity in the Telerik Data Access model can expose binary large objects, also known as BLOBs. This binary data might represent video or audio streams, images, document files, or other types of binary media. Binary large objects (BLOBs) need different treatment, because they can contain gigabytes of data and this can affect the application performance. That's why Telerik Data Access provides special support (API) for working with BLOBs.
In this topic, you will see:
- How to work with the BinaryStream type
- How to read binary data from the database
- How to write binary data to the database
Working with the BinaryStream Type
The BinaryStream type is a special type that exposes a stream around a database binary field. By default when you map a table with a binary column, the corresponding property should be of type byte[].
The BinaryStream type can be used against varbinary(MAX) columns in MSSQL and the corresponding ones in other backends. For example, if you try to use it with a column of type Image, you will get an exception. The support backends/sql types are as follows:
- MSSQL - varbinary(MAX)
- PostgreSQL - bytea
- MySql - longblob
- Oracle - blob
public partial class Category
{
public virtual int CategoryID { get; set; }
public virtual string CategoryName { get; set; }
public virtual string Description { get; set; }
public virtual byte[] Picture { get; set; }
}
Partial Public Class Category
Public Overridable Property CategoryID() As Integer
Public Overridable Property CategoryName() As String
Public Overridable Property Description() As String
Public Overridable Property Picture() As Byte()
End Class
To use the new BinaryStream type you have to change the type of the property:
public partial class Category
{
public virtual int CategoryID { get; set; }
public virtual string CategoryName { get; set; }
public virtual string Description { get; set; }
public virtual BinaryStream Picture { get; set; }
}
Partial Public Class Category
Public Overridable Property CategoryID() As Integer
Public Overridable Property CategoryName() As String
Public Overridable Property Description() As String
Public Overridable Property Picture() As BinaryStream
End Class
Reading Binary Data From the Database
The following example shows how to use the Read method of the BinaryStream class to read an image from the database and save it on the local hard drive. The Read method reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
using ( FluentModel dbContext = new FluentModel() )
{
FileStream stream = new FileStream( "CategoryImage.jpg",
FileMode.Create, FileAccess.Write );
BinaryWriter writer = new BinaryWriter( stream );
Category firstCategory = dbContext.Categories.Last();
int numBytesToRead = ( int )firstCategory.Picture.Length;
byte[] bytes = new byte[65536];
int bytesRead = 1;
while ( numBytesToRead > 0 && bytesRead > 0 )
{
bytesRead = firstCategory.Picture.Read( bytes, 0,
Math.Min( numBytesToRead, bytes.Length ) );
writer.Write( bytes );
numBytesToRead -= bytesRead;
}
writer.Flush();
writer.Dispose();
}
Using dbContext As New FluentModel()
Dim stream As New FileStream("CategoryImage.jpg", FileMode.Create,
FileAccess.Write)
Dim writer As New BinaryWriter(stream)
Dim firstCategory As Category = dbContext.Categories.Last()
Dim numBytesToRead As Integer = CInt(Fix(firstCategory.Picture.Length))
Dim bytes(65535) As Byte
Dim bytesRead As Integer = 1
Do While numBytesToRead > 0 AndAlso bytesRead > 0
bytesRead = firstCategory.Picture.Read(bytes, 0,
Math.Min(numBytesToRead, bytes.Length))
writer.Write(bytes)
numBytesToRead -= bytesRead
Loop
writer.Flush()
writer.Dispose()
End Using
Writing Binary Data to the Database
The following example shows how to use the Write method of the BinaryStream class to insert an image in the database. The Write method writes a sequence of bytes to the current stream and advances the current position within the stream by the number of bytes written. Another important thing to note is the Append property of the BinaryStream class. It indicates whether the stream will replace the binary field with update statements or will just append the new data.
Note that the BinaryStream property is automatically initialized by the runtime. You don't need to explicitly create a new instance.
using ( FluentModel dbContext = new FluentModel() )
{
Category category = new Category();
category.CategoryName = "Demo Category";
category.Description = "Demo Description";
dbContext.Add( category );
dbContext.SaveChanges();
using ( FileStream stream = File.OpenRead( "Input.jpg" ) )
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ( ( bytesRead = stream.Read( buffer, 0, buffer.Length ) ) > 0 )
{
category.Picture.Write( buffer, 0, bytesRead );
}
}
category.Picture.Flush();
dbContext.SaveChanges();
}
Using dbContext As New FluentModel()
Dim _category As New Category()
_category.CategoryName = "Demo Category"
_category.Description = "Demo Description"
dbContext.Add(_category)
dbContext.SaveChanges()
Using stream As FileStream = File.OpenRead("Input.jpg")
Dim buffer(1023) As Byte
Dim bytesRead As Integer = 0
bytesRead = stream.Read(buffer, 0, buffer.Length)
Do While bytesRead > 0
_category.Picture.Write(buffer, 0, bytesRead)
bytesRead = stream.Read(buffer, 0, buffer.Length)
Loop
End Using
_category.Picture.Flush()
dbContext.SaveChanges()
End Using