I am getting an error while running my ASP.NET Core 8 MVC app.
These are my controller methods hit by Ajax calls by Kendo controls:
public List<Location> GetLocations()
{
return _db.Locations.ToList();
}
public List<Region> GetRegions()
{
return _db.Regions.ToList();
}
Now as the MS documentation says, it's because of database operations happening at the same time.
When I change the code to the following, it works:
public async Task<List<Location>> GetRegions()
{
return _db.Locations.ToList();
}
public async Task<List<Region>> GetRegions()
{
return _db.Regions.ToList();
}
I don't understand how this works. The same code can also hit database at the same time.
My only theory is that, Framework calls them
await GetLocation();
await GetRegion();
Or the framework just holds the new async calls until the executing ones are completed.
But that defeats the purpose of async
.
Please let me know.
Thanks in advance
I am getting an error while running my ASP.NET Core 8 MVC app.
These are my controller methods hit by Ajax calls by Kendo controls:
public List<Location> GetLocations()
{
return _db.Locations.ToList();
}
public List<Region> GetRegions()
{
return _db.Regions.ToList();
}
Now as the MS documentation says, it's because of database operations happening at the same time.
When I change the code to the following, it works:
public async Task<List<Location>> GetRegions()
{
return _db.Locations.ToList();
}
public async Task<List<Region>> GetRegions()
{
return _db.Regions.ToList();
}
I don't understand how this works. The same code can also hit database at the same time.
My only theory is that, Framework calls them
await GetLocation();
await GetRegion();
Or the framework just holds the new async calls until the executing ones are completed.
But that defeats the purpose of async
.
Please let me know.
Thanks in advance
Share Improve this question edited Mar 31 at 3:51 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Mar 30 at 23:38 GulumalGulumal 612 silver badges8 bronze badges 5 |2 Answers
Reset to default 0I had a test within my 8 MVC app, I created a button click event handler which would send 2 ajax requests to call my controller action. These 2 requests will call 2 methods like what you shared but I didn't get your exception. Based on my log, I can also see that the 2 requests has 2 different session ids.
private readonly ApplicationDbContext _context;
private readonly ILogger<MoviesController> _logger;
public MoviesController(ApplicationDbContext context, ILogger<MoviesController> logger)
{
_context = context;
_logger = logger;
}
public string test1() {
var sessionId = HttpContext.Session.Id;
_logger.LogError("sessionId is =====================: "+sessionId);
GetMovie();
return "success1";
}
public string test2()
{
var sessionId = HttpContext.Session.Id;
_logger.LogError("sessionId2 is =====================: " + sessionId);
GetMovieDesc();
return "success2";
}
public List<Movie> GetMovie()
{
return _context.Movie.ToList();
}
public List<MovieDesc> GetMovieDesc()
{
return _context.MovieDesc.ToList();
}
Based on this section, we know that we should avoid using the same DbContext
instance to run multiple parallel operations as DbContext
is not thread safe. Therefore I deduce you are using the same _db
instance to get your data from database. To resolve the issue, following the document:
always await async calls immediately, or use separate DbContext instances for operations that execute in parallel
The reason why your code could work only change the response type to asyn Task
without changing to use await _db.Locations.ToListAsync();
shall relate to how .Net core handle tasks, if we don't add await
but only return Task, your app will return the Task object immediately, and ASP.NET Core awaits it later --> you have await GetLocation();
which will wait for task completion as well. While both setting await and Task, it will wait for the task to complete inside the method, then return the result. I didn't find official MS document explained it, but I find this case. I trust it could help to understand.
@Tiny Wang
You can reproduce it with following code in a form.
@(Html.Kendo().DropDownListFor(c => c.reg)
.Filter(FilterType.Contains)
.OptionLabel("Please select a region...")
.DataTextField("RegName")
.DataValueField("RegID")
.Events( e=>e.Change("onRegionChange"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetRegions", "Location");
});
})
)
@Html.HiddenFor(m => m.LocationId)
@(
Html.Kendo().DropDownListFor(c => Location)
.Filter(FilterType.Contains)
.OptionLabel("Please select an office...")
.DataTextField("OfficeName")
.DataValueField("OfficeId")
.Events(e => e.Change("changeDefLocation"))
.AutoBind(true)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetLocations", "Location").Data("additionalInfo");
});
})
)
@(Html.Kendo().MultiSelectFor(m => m.OtherLocation)
.DataTextField("OfficeName")
.DataValueField("OfficeId")
.DataSource(dataSource =>
dataSource.Read(x => x.Action("GetLocationss", "Location").Data("sdaAndLocinfo"))
.ServerFiltering(false)
)
.Events( x=>x.Change("OnOfficeChange"))
.AutoBind(true)
)
_db
defined and created? Are you using DI (dependency injection) to create it? – Peter B Commented Mar 31 at 0:35await _db.xx.ToListAsync();
instead ofToList()
– Tiny Wang Commented Mar 31 at 7:35