0

I have a requirement to allow my Intranet .NET web portal users to send free-text SQL query to the backend (Read-only DB on SQL Server 2014) and get the results in Excel, while this works fine for most cases but the code fails when the results are too big (around 350mb, 250k records) to be processed.

My first attempt was to get the results directly as JSON serialized into a data table on the frontend.

That failed since iterating through the results set would throw System.OutOfMemoryException:

private JavaScriptSerializer _serializer;
return _serializer.Serialize(results));

So decided its not a good thing anyway to display this amount of results on the interface directly since IE will struggle. So went to the option of prompting users to download an Excel copy of the output by saving the results into a JSON file then read the file and convert it to Excel:

using (StreamReader sr = new StreamReader(filePath))
String json;
// Read and display lines from the file until the end of 
// the file is reached.
while ((json = sr.ReadLine()) != null)
{
    Console.WriteLine(json);}
}

However the ReadLine() method is throwing the same exception, it is good to note that the ReadLine is failing due to the fact the file consists of only one line otherwise I would try and iterate over the lines line by line.

Lastly I tried access the IEnumerable directly to write it into Excel

var results = new ReportProcess().ExecuteSql(sqlQuery, out string eventMessage);
List<object> queryObjects = new List<object>();


            foreach (var result in results)
            {
                queryObjects.Add(result);
            }

            var row = queryObjects.FirstOrDefault();
            if (row != null)
            {
                var recordType = row.GetType();

                using (var excelFile = new ExcelPackage())
                {
                    MemberInfo[] membersToInclude = recordType
                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                        .ToArray();

                    var worksheet = excelFile.Workbook.Worksheets.Add("Sheet1");

                    worksheet.Cells.LoadFromCollection(queryObjects, true,
                        OfficeOpenXml.Table.TableStyles.None,
                        BindingFlags.Instance | BindingFlags.Public,
                        membersToInclude);


                    fileName = Guid.NewGuid() + ".xlsx";
                    excelFile.SaveAs(new FileInfo(HttpContext.Current.Server.MapPath("~/temp/") + fileName));

                }
            }

And again the code fails around

foreach (var result in results)
{
   queryObjects.Add(result);
}

With the same exception

So now I'm stuck around the fact that no matter what I try to do to iterate through the IEnumerable resuls, I would always get the OutOfMemory Exception.

I have also tried to increase the memory allocated to objects by setting the gcAllowVeryLargeObjects to true in the web.config but to no avail:

 <runtime>
    <gcAllowVeryLargeObjects enabled="true"/>
 </runtime>

Other attempt:

enter image description here

Googling around did not bring anything to resolve the issue, any suggestions/ideas?

Maya
  • 1,414
  • 5
  • 22
  • 43

1 Answers1

0

Eventually I had to rewrite my code to implement external libraries to serialize CSV using CsvHelper library

using (StreamReader sr = new StreamReader(filePath))
                {
                    var csvReader = new CsvReader(sr);
                    var records = csvReader.GetRecords<object>();
                    var result = string.Empty;
                    try
                    {
                        return JsonConvert.SerializeObject(new ServerData(records, _eventMessage));
                    }
                    catch (Exception ex)
                    {
                        _eventMessage.Level = EventMessage.EventLevel.Error;
                    }


                    return _serializer.Serialize(new ServerData(result, _eventMessage));
                }

That seems to work fine with large data set, OutOfMemory Exception is no longer appearing

Maya
  • 1,414
  • 5
  • 22
  • 43