Initial data:

An old project on the .NET Framework, a database on SQL Server, the files are stored in a table in an IMAGE type field. Files of various sizes, from tens of bytes to hundreds of megabytes. I know that this is all outdated, but at the moment there is no possibility to change the structure of the database and, in the foreseeable future, it is not foreseen, alas.

A new project is a service, web api on ASP.NET Core, with the same database as the data source.

Task:

At the request of the client to receive files from the database and give in the form FileStreamResult .


Actually the task itself is not difficult, from the word at all, but there is one gag that I would like to solve beautifully.

And so, the current solution is organized as follows:

  1. In order not to upload huge files to the service’s memory, I’ve been working the SqlReader , which allows you to create a stream to the field containing the contents of the file.

  2. This stream is copied to a temporary file on the disk, since if the reader is tapped, the connection is closed and the data will be inaccessible, therefore you cannot transfer this stream directly to FileStreamResult .

  3. The stream is detached from the temporary file, given to FileStreamResult and safely dispelled by the ASP.NET Core kernel upon completion of data transfer to the client.

  4. In the background the service is spinning, which periodically cleans this improvised cache.


And now the actual question: is it possible to do without copying data to a file, without explicitly loading the entire file content into the RAM? Or maybe there is just a more beautiful solution that I missed / didn't find?

Instead of copying to a file, it would be possible to send the stream from SqlReader to FileStreamResult immediately, but then you need to ensure an open connection until the end of the data transfer, hence SqlReader cannot be SqlReader , and if the reader is not disarmed, then how to do it after the data transfer is completed, if none links to unclosed SqlReader not left? Work with the database is organized through internal services that are injected into the controller, built-in ASP.NET Core, DI-means. Or all the same, the reader can be killed "later" (well, or he will die, what is hard to believe) and I did not finish reading something about ASP.NET Core?

    1 answer 1

    The variant is a successor to FileStreamResult , which accepts (and remembers) in the SqlReader constructor, rewrites the ExecuteResult and closes the SqlReader after calling base.ExecuteResult .

    • damn, about the possibility of inheritance, I did not even think, we must try - rdorn
    • @rdorn You probably have SqlConnection open. That is, the heir must give references to everything that should be closed after the completion of reading. - Igor
    • No, the reader has settings in the settings to close the connection when the reader is closed, so everything is fine with that. - rdorn
    • A great option, compact, neat and the speed of work is excellent. Thank. - rdorn
    • @rdorn Glad to help. - Igor