Working with 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:
- BinaryStream Class
- Reading Binary Data From the Database
- Writing Binary Data to the Database
- How to Set a BinaryStream Property to Null
- Attaching Objects with BinaryStream Properties
BinaryStream Class
The Telerik.OpenAccess.BinaryStream type is a special type that exposes a stream around a database binary field.
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
It derives from the Stream class, so you can use it as any other Stream object.
The BinaryStream type is not serializable.
The most important methods and properties of the BinaryStream class are as follows:
- Append - indicates whether the stream will replace the binary field with update statements or will just append the new data. The Append property is demonstrated in the Writing Binary Data to the Database example.
- Dispose - disposes the stream, by writing any changes to the backing store and closing the stream to release resources. The specific moment is that the Dispose method will flush all reads and writes.
- Seek - sets the position within the current stream.
- SetLength - sets the length of the current stream to the given value.
Reading Binary Data From the Database
The main purpose of the BinaryStream class is to read/write BLOBs from/to the database. The following example demonstrates how to read binary data from the database. In this particular example, you will read an image from the database and save it on the local hard drive.
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
Analogically, you can write binary data in the database.
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
How to Set a BinaryStream Property to Null
The following example demonstrates how to set a BinaryStream property to null.
using (FluentModel dbContext = new FluentModel())
{
Category category = dbContext.Categories.FirstOrDefault();
category.Picture = null;
dbContext.SaveChanges();
}
Using dbContext As New FluentModel()
Dim _category As Category = dbContext.Categories.FirstOrDefault()
_category.Picture = Nothing
dbContext.SaveChanges()
End Using
Attaching Objects with BinaryStream Properties
This section demonstrates how to attach and detach objects with BinaryStream properties. Basically, when you want to attach an object with a BinaryStream property you have to perform the following steps:
- Pass the object to the AttachCopy method of the context.
- Call FlushChanges.
- Initialize the BinaryStream property.
- Call SaveChanges.
using ( FluentModel dbContext = new FluentModel() )
{
Category category = new Category();
category.CategoryName = "Demo Category";
category.Description = "Demo Descripton";
Category attachedCategory = dbContext.AttachCopy( category );
dbContext.FlushChanges();
FileStream stream = File.OpenRead( "Input.jpg" );
int numBytesToWrite = ( int )stream.Length;
byte[] bytes = new byte[65536];
int bytesRead = 1;
while ( numBytesToWrite > 0 && bytesRead > 0 )
{
bytesRead = stream.Read( bytes, 0, Math.Min( numBytesToWrite, bytes.Length ) );
attachedCategory.Picture.Write( bytes, 0, bytes.Length );
numBytesToWrite -= bytesRead;
}
dbContext.SaveChanges();
stream.Dispose();
}
Using dbContext As New FluentModel()
Dim _category As New Category()
_category.CategoryName = "Demo Category"
_category.Description = "Demo Descripton"
Dim attachedCategory As Category = dbContext.AttachCopy(_category)
dbContext.FlushChanges()
Dim stream As FileStream = File.OpenRead("Input.jpg")
Dim numBytesToWrite As Integer = CInt(Fix(stream.Length))
Dim bytes(65535) As Byte
Dim bytesRead As Integer = 1
Do While numBytesToWrite > 0 AndAlso bytesRead > 0
bytesRead = stream.Read(bytes, 0, Math.Min(numBytesToWrite, bytes.Length))
attachedCategory.Picture.Write(bytes, 0, bytes.Length)
numBytesToWrite -= bytesRead
Loop
dbContext.SaveChanges()
stream.Dispose()
End Using