Как снизить использование памяти в API FileStreamResult - PullRequest
1 голос
/ 04 февраля 2020

Прямо сейчас у меня есть API, который получает много результатов (800k), и он должен анализировать и передавать их как CSV. Рабочий код (вид), который у меня есть, такой:

            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"
            };

Однако, похоже, все это помещается в память и сохраняется с использованием до 300 МБ памяти. Насколько я понимаю, это происходит в выражении foreach. Есть ли способ, которым я пишу строку, поток, а затем избавиться от нее из памяти? Моя цель состоит в том, чтобы добиться чего-то подобного без использования большого количества памяти

Я также пытался сделать это таким образом, который работает для одного вызова, но если одновременно выполняется несколько вызовов API, возникает странное поведение

 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 Ответ

3 голосов
/ 04 февраля 2020

Вы можете записывать данные непосредственно в тело ответа без необходимости помещать их в MemoryStream.

Редактирование запроса: это то, что я сделал

//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));
}

, и, похоже, оно работает нормально

...