从 Web Api 上打开的 Db 连接返回流:结束时关闭连接

Returning stream from an open DbConnection on WebApi: close connection when ending

我正在从 SQL 数据库中读取 varbinary(max) 字段作为 Stream... 我想 return 该流作为文件。

我正在使用 EF Core,但是 EF Core 映射需要(或者我不太了解)将 varbinary 字段映射到字节数组,这意味着将整个字段读入内存,然后创建从 WebApi 控制器到 return 的流。

所以我想知道如何在关闭数据 reader 的同时正确 return 流。我知道 ASP.NET 控制器,当 return 将流作为文件(使用 FileStreamResult)时确实会在最后关闭流,但在这种情况下,我还需要关闭连接(我手动打开)发送流后,我不确定如何处理。

代码将等同于此(我已编辑代码以简化它,可能会有拼写错误):

public async Task<IActionResult> GetFile(Guid fileId)
{
    var query = @$"SELECT FileBinary
                      FROM {SchemaName}.{TableName} 
                      WHERE {GetSqlColumnName(nameof(Id))} = @id";

    var idParameter = new SqlParameter("id", fileId) { DbType = DbType.Guid };
    await using var command = DbContext.Database.GetDbConnection().CreateCommand();
    command.CommandText = query;
    command.CommandType = CommandType.Text;
    command.Parameters.Add(idParameter);
    // DbContext would be the EF context
    await DbContext.Database.OpenConnectionAsync().ConfigureAwait(false);
    await using var reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow).ConfigureAwait(false);
    await reader.ReadAsync();
    var stream = reader.GetStream(0);
    return new FileStreamResult(stream, "application/pdf");
}

这段代码似乎工作正常,实际文件似乎是从数据 reader 直接流式传输到 http 客户端...但是在这段代码中,打开的数据库连接将在那里保持打开状态(并且如果我没记错的话,我听说 EF 上的 dbcontext 会重用池中的连接,但如果它已经打开,它不会尝试自行关闭它,从而在那里留下一个“始终打开”的连接).我在这方面可能是错的(如果我错了,那么这将解决它并且不会有问题)。

如果它实际上是打开的(我不想要),在流完全发送后是否有任何方法可以关闭它?

采用@Steeeve 的想法,我围绕流创建了一个包装器,其中包括数据reader 和连接,并且closes/disposes 当流是closed/disposed.

由于代码很长,I've created a gist on github,虽然它是非常简单的代码。

似乎工作正常