How to lower memory usage in FileStreamResult api

China☆狼群 提交于 2021-02-19 08:37:11

问题


Right now I have an api that gets many results (800k) and it should parse and stream them as CSV. The (kind of) working code I have is this

            var query = context.address.AsNoTracking();

            MemoryStream memoryStream = new MemoryStream();
            StreamWriter writer = new StreamWriter(memoryStream);

              foreach (var row in query)
            {
                writer.WriteLine(row.Name+","+row.Surname+","+row.BirthDate);

            }

            writer.Flush();                                 
            memoryStream.Seek(0, SeekOrigin.Begin);
            return new FileStreamResult(memoryStream, "application/octet-stream")
            {
                FileDownloadName = "DataFile.csv"
            };

However this seems to put everything into memory, and store it using up 300 mb of memory. As i understand it, that happens in the foreach statement. Is there a way that i write the line, stream it, and then dispose of it from memory? My goal is to achieve something similar to this without using so much memory

I have also tried it this way, which works for one call, but if multiple api calls are made at the same time, there is weird behaviour

 public async Task makeDif()
    {




            //var query = context.Adresar.AsNoTracking();
        var query = context.Adresar.Select(x => string.Join(",", x.Ime, x.Prezime, x.Datarag + Environment.NewLine)).AsNoTracking();
        Response.ContentType = "application/json";
        Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes("ime,prezime,datarag" + Environment.NewLine)); 
        foreach (var row in query)
                {
               await Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes(row));

            }}

回答1:


You can write data directly to response body without need of putting it into a MemoryStream.

Asker edit: This is what I did

//var query = context.Adresar.AsNoTracking();
var query = context.Adresar.Select(x => string.Join(",", x.Ime, x.Prezime, x.Datarag + Environment.NewLine)).AsNoTracking();
Response.ContentType = "application/json";
Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes("ime,prezime,datarag" + Environment.NewLine)); 
foreach (var row in query)
{
    await Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes(row));
}

and it seems to work fine



来源:https://stackoverflow.com/questions/60054236/how-to-lower-memory-usage-in-filestreamresult-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!