TLDR; I have an ASP.NET Core 5.0 API that's sitting at AWS. It makes a large call to MSSQL db to return ~1-4k rows of data. A single request is fine, taking ~500ms, but when multiple requests come in about the same time (4-5), the request slows to ~2000ms per call. What's going on?
There's not much more to state than what I have above. I open a connection to our DB then initialize a SqlCommand.
using (var connection = new SqlConnection(dbConnection)) connection.Open(); using (SqlCommand command = new SqlCommand(strSQLCommand)) I've tried both filling a datatable with SqlDataAdapter and using a SqlDataReader to fill up a custom object, I get similar slow downs either way. As stated above the query returns ~1-4k rows of data of varying types. And Postman says the returned Json data is about 1.95MB of size after decompression. The slowdown only occurs when multiple requests come in around the same time. I don't know if it's having trouble with multiple connections to the db, or if it's about the size of the data and available memory. Paging isn't an option, the request needs to return that much data.
This all occurs within a HttpGet function
[HttpGet] [Route("Foo")] [Consumes("application/json")] [EnableCors("DefaultPolicy")] public IActionResult Foo([FromHeader] FooRequest request) { ///stuff DataTable dt = new DataTable(); using (var connection = new SqlConnection(_dataDBConnection)) { timer.Start(); connection.Open(); using (SqlCommand command = new SqlCommand( "SELECT foo.name, bar.first, bar.second, bar.third, bar.fourth FROM dbo.foo with(nolock) JOIN dbo.bar with(nolock) ON bar.name = foo.name WHERE bar.date = @date", connection)) { command.Parameters.AddWithValue("@date", request.Date.ToString("yyyyMMdd")); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { adapter.Fill(dt); } } timer.Stop(); long elapsed = timer.ElapsedMilliseconds; } ///Parse the data from datatable into a List<object> and return ///I've also used a DataReader to put the data directly into the List<object> but experienced the same slowdown. ///response is a class containing an array of objects that returns all the data from the SQL request return new JsonResult(response); } Any insights would be appreciated!
--EDIT AFTER ADDITOINAL TESTING---
[HttpGet] [Route("Foo")] [Consumes("application/json")] [EnableCors("DefaultPolicy")] public IActionResult Foo([FromHeader] FooRequest request) { ///stuff using (var connection = new SqlConnection(_dataDBConnection)) { connection.Open(); ///This runs significantly faster using (SqlCommand command = new SqlCommand(@"dbo.spGetFoo", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@date", request.date.ToString("yyyyMMdd")); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { ///Add data to list to be returned } } } } ///Parse the data from datatable into a List<object> and return ///I've also used a DataReader to put the data directly into the List<object> but experienced the same slowdown. ///response is a class containing an array of objects that returns all the data from the SQL request return new JsonResult(response); } --FINAL EDIT PLEASE READ--
People seem to be getting caught up on the DataAdapter and Fill portion instead of reading the full post. So, I'll include a final example here that provides the same issue above.
[HttpGet] [Route("Foo")] [Consumes("application/json")] [EnableCors("DefaultPolicy")] public async Task<IActionResult> Foo([FromHeader] FooRequest request) { ///stuff using (var connection = new SqlConnection(_dataDBConnection)) { await connection.OpenAsync(); ///This runs significantly faster using (SqlCommand command = new SqlCommand(@"dbo.spGetFoo", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@date", request.date.ToString("yyyyMMdd")); using (SqlDataReader reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { ///Add data to list to be returned } } } } ///Parse the data from datatable into a List<object> and return ///response is a class containing an array of objects that returns all the data from the SQL request return new JsonResult(response); }