I am trying to stream contents stored in sql server as varbinary(max) to the client. I am able to make it work however the connection will stay open until garbage collection. If I dispose the connection, reader or steam prior to returning the results it causes an object disposed error.
I am looking to avoid copying the data into memory (as it can be large) while also properly disposing of the object when done. What would be the best way to achieve both of these goals.
I am using .NET Core 2.0 if that is relevant.
Update: This is not a duplicate from others (How do I dispose my filestream when implementing a file download in ASP.NET?) as I am not asking how to dispose of the stream but rather how to dispose of the related connection object. My question is more about the proper way of ensure the connection object is disposed
The code below successfully returns results but leaves an non-disposed connection:
public async Task<IActionResult> DownloadFile(Guid FileId)
{
var connection = new SqlConnection(DatabaseService.ConnectionString);
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "select FileName, FileContent from Files where FileId=@FileId";
command.CommandType = System.Data.CommandType.Text;
command.Parameters.AddWithValue("@FileId", FileId);
var reader = await command.ExecuteReaderAsync(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleRow);
if (!await reader.ReadAsync())
return NotFound();
var attachmentName = Convert.ToString(reader[0]);
var stream = reader.GetStream(1);
var response = File(stream, "application/octet-stream", attachmentName);
return response;
}
This code below disposes of the object but fails to stream the content because it is disposed first
public async Task<IActionResult> DownloadFile(Guid FileId)
{
using (var connection = new SqlConnection(DatabaseService.ConnectionString))
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandText = "select FileName, FileContent from Files where FileId=@FileId";
command.CommandType = System.Data.CommandType.Text;
command.Parameters.AddWithValue("@FileId", FileId);
using (var reader = await command.ExecuteReaderAsync(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleRow))
{
if (!await reader.ReadAsync())
return NotFound();
var attachmentName = Convert.ToString(reader[0]);
using (var stream = reader.GetStream(1))
{
var response = File(stream, "application/octet-stream", attachmentName);
return response;
}
}
}
}
}