I have an Asp.Net Core 2.1, MVC, C# Web application in Visual Studio 2017 15.7.5. My Nuget packages show that I am using Microsoft.EntityFrameworkCore.Tools 2.1.1.
In my coding shown at the end of this post, my program hangs up on this statement:
await _context.SaveChangesAsync();
and never returns control to the next statement. I used the Visual Studio debugger to stop on the statement after that one and waited ten minutes. It never gave control back.
I also tried it this way and got the same results:
Does anyone know how to debug this issue? Is there some log that I can look at?
Thanks,
Tony
Here is my code:
public class ProductListViewComponent : ViewComponent
{
private readonly ChinavasionAPIContext _context;
private readonly IHubContext<ChvHub> _hubContext;
public ProductListViewComponent(IHubContext<ChvHub> hubcontext, ChinavasionAPIContext context)
{
_context = context;
_hubContext = hubcontext;
}
#region snippet1
public async Task<IViewComponentResult> InvokeAsync()
{
//string MyView = "Default";
var items = await GetItemsAsync();
await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "", "=============================================== Ready to Display Lakeside and Chinavasion Products ===============================================");
return View(items);
}
public async Task<List<ProductViewModel>> GetItemsAsync()
{
var model = new AccessModel();
model.UserAccessModel = _context.UserAccessModels.Single(a => a.ID == 1);
var accessToken = (model.UserAccessModel.AccessToken ?? TempData["accessToken"]).ToString();
var serverUrl = (model.UserAccessModel.ServerUrl ?? TempData["serverUrl"]).ToString();
var nopApiClient = new ApiClient(accessToken, serverUrl);
MultipleProductModel multipleProductModel = new MultipleProductModel();
List<Category> categories = new List<Category>();
string jsonUrl = $"/api/products/count";
object productsCount = nopApiClient.Get(jsonUrl);
var nopProductsCount = JsonConvert.DeserializeObject<ProductsCount>(productsCount.ToString());
int sinceID = 0;
int productCount = 0;
await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "", "============================================= Starting Lakeside Product Retrieval from Live Database ==============================================");
do
{
productCount += 1;
await this._hubContext.Clients.All.SendAsync("ReceiveMessage", productCount.ToString(), " Downloading Lakeside products");
jsonUrl = $"/api/products?limit=250&since_id=" + sinceID.ToString() + $"&fields=id,sku,name,images,categories";
object productsData = nopApiClient.Get(jsonUrl);
var productsRootObject = JsonConvert.DeserializeObject<ProductsRootObject>(productsData.ToString());
multipleProductModel.MProductsApi.AddRange(productsRootObject.Products);
await _context.AddRangeAsync(productsRootObject.Products);
await _context.SaveChangesAsync();
var last = multipleProductModel.MProductsApi.LastOrDefault();
sinceID = Convert.ToInt16(last.Id);
} while (multipleProductModel.MProductsApi.Count < nopProductsCount.Count);
}
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ChinavasionAPI.DTOs
{
public class ProductsRootObject
{
[JsonProperty("products")]
public List<ProductApi> Products { get; set; }
}
}
using Newtonsoft.Json;
using System.Collections.Generic;
{
public class ProductApi
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("sku")]
public string Sku { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("images")]
public List<Image> Images { get; set; }
[JsonProperty("categories")]
public string Categories { get; set; }
}
public class Image
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("position")]
public int Position { get; set; }
[JsonProperty("src")]
public string Src { get; set; }
[JsonProperty("attachment")]
public string Attachment { get; set; }
}
}
using System.Collections.Generic;
using ChinavasionAPI.DTOs;
namespace ChinavasionAPI.Models.CAPIViewModels
{
public class MultipleProductModel
{
public List<ProductApi> MProductsApi { get; set; }
public List<Product> MProducts { get; set; }
public MultipleProductModel()
{
this.MProductsApi = new List<ProductApi>();
this.MProducts = new List<Product>();
}
}
}
If there is blocking call inside asynchronous call / path, it could cause deadlock if the both the threads waiting for each other to complete (SynchronizationContext).
This is what happened in your asp.net mvc application.
There is a blocking (sync) call in your method,
object productsData = nopApiClient.Get(jsonUrl);
Fix this, by calling the asynchronous version of the method if available. eg:await nopApiClient.GetAsync(jsonUrl) ;
Note : Fix the both two places where you called blocking Get method inside the method.
I put in a try/catch on the code where it was hanging up. I saw this error:
An error occurred while updating the entries. See the inner exception for details.
Cannot insert explicit value for identity column in table 'ProductApis' when IDENTITY_INSERT is set to OFF.
After Googling that error, I found articles that suggested putting this annotation:
[DatabaseGenerated(DatabaseGeneratedOption.None)]
on the Id properties for the ProductApi and Image models.
That allowed me to run the program without getting the hangup and it populated the tables.
I very much appreciate your help in trying to fix this issue.
Member
34 Points
345 Posts
Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 03, 2018 12:30 PM|TGirgenti|LINK
Hello,
I have an Asp.Net Core 2.1, MVC, C# Web application in Visual Studio 2017 15.7.5. My Nuget packages show that I am using Microsoft.EntityFrameworkCore.Tools 2.1.1.
In my coding shown at the end of this post, my program hangs up on this statement:
and never returns control to the next statement. I used the Visual Studio debugger to stop on the statement after that one and waited ten minutes. It never gave control back.
I also tried it this way and got the same results:
Does anyone know how to debug this issue? Is there some log that I can look at?
Thanks,
Tony
Here is my code:
public class ProductListViewComponent : ViewComponent { private readonly ChinavasionAPIContext _context; private readonly IHubContext<ChvHub> _hubContext; public ProductListViewComponent(IHubContext<ChvHub> hubcontext, ChinavasionAPIContext context) { _context = context; _hubContext = hubcontext; } #region snippet1 public async Task<IViewComponentResult> InvokeAsync() { //string MyView = "Default"; var items = await GetItemsAsync(); await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "", "=============================================== Ready to Display Lakeside and Chinavasion Products ==============================================="); return View(items); } public async Task<List<ProductViewModel>> GetItemsAsync() { var model = new AccessModel(); model.UserAccessModel = _context.UserAccessModels.Single(a => a.ID == 1); var accessToken = (model.UserAccessModel.AccessToken ?? TempData["accessToken"]).ToString(); var serverUrl = (model.UserAccessModel.ServerUrl ?? TempData["serverUrl"]).ToString(); var nopApiClient = new ApiClient(accessToken, serverUrl); MultipleProductModel multipleProductModel = new MultipleProductModel(); List<Category> categories = new List<Category>(); string jsonUrl = $"/api/products/count"; object productsCount = nopApiClient.Get(jsonUrl); var nopProductsCount = JsonConvert.DeserializeObject<ProductsCount>(productsCount.ToString()); int sinceID = 0; int productCount = 0; await this._hubContext.Clients.All.SendAsync("ReceiveMessage", "", "============================================= Starting Lakeside Product Retrieval from Live Database =============================================="); do { productCount += 1; await this._hubContext.Clients.All.SendAsync("ReceiveMessage", productCount.ToString(), " Downloading Lakeside products"); jsonUrl = $"/api/products?limit=250&since_id=" + sinceID.ToString() + $"&fields=id,sku,name,images,categories"; object productsData = nopApiClient.Get(jsonUrl); var productsRootObject = JsonConvert.DeserializeObject<ProductsRootObject>(productsData.ToString()); multipleProductModel.MProductsApi.AddRange(productsRootObject.Products); await _context.AddRangeAsync(productsRootObject.Products); await _context.SaveChangesAsync(); var last = multipleProductModel.MProductsApi.LastOrDefault(); sinceID = Convert.ToInt16(last.Id); } while (multipleProductModel.MProductsApi.Count < nopProductsCount.Count); }
Participant
980 Points
198 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 05, 2018 05:42 AM|Wenushka|LINK
Hi TGirgenti,
If there is blocking call inside asynchronous call / path, it could cause deadlock if the both the threads waiting for each other to complete (SynchronizationContext).
This is what happened in your asp.net mvc application.
There is a blocking (sync) call in your method,
object productsData = nopApiClient.Get(jsonUrl);
Fix this, by calling the asynchronous version of the method if available. eg: await nopApiClient.GetAsync(jsonUrl) ;
Note : Fix the both two places where you called blocking Get method inside the method.
Further go through the followings,
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
https://gist.github.com/jonlabelle/841146854b23b305b50fa5542f84b20c
Thanks,
Wenushka
Member
34 Points
345 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 05, 2018 04:55 PM|TGirgenti|LINK
Hello Wenushka.
Thanks for your help with this issue.
There is one thing that I am confused about. If the blocking call is causing the problem when it gets to this:
await _context.SaveChangesAsync();
why does it not hangup on the await prior to that one?
I will read the information you pointed out and I will try to make the blocking Get you pointed out to an await
Thanks,
Tony
Member
34 Points
345 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 07, 2018 02:33 AM|TGirgenti|LINK
Hello Wenushka.
I tried your idea of making the calling of the asynchronous version of the methods and it did not work.
I changed all of my methods to public async Task and it still hangs up on "await _context.SaveChangesAsync();"
Does anyone have any idea of how to fix this problem?
Thanks,
Tony
Participant
980 Points
198 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 07, 2018 05:05 AM|Wenushka|LINK
Hi TGirgenti,
Could you share the implementation of the ,
or two methods of that class,
Thanks,
Wenushka
Member
34 Points
345 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 07, 2018 12:59 PM|TGirgenti|LINK
Wenushka,
Here is my context file:
Thanks for your help.
Tony
Participant
980 Points
198 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 08, 2018 09:02 AM|Wenushka|LINK
hi TGirgenti,
Change how the entities is added before committing the changes to db.
Change,
await _context.AddRangeAsync(productsRootObject.Products);
with,
_context.ProductApis.AddRange(productsRootObject.Products);
Note: In adding the entities, you don't have to call async version of DbContext unless we have special requirement mentioned here.
https://docs.microsoft.com/en-us/ef/core/api/microsoft.entityframeworkcore.dbcontext
https://docs.microsoft.com/en-us/ef/core/api/microsoft.entityframeworkcore.dbset-1
Finally, commit the changes as usual with the,
await _context.SaveChangesAsync();
Member
34 Points
345 Posts
Re: Why does my web application hang up on "await _context.SaveChangesAsync();"
Aug 09, 2018 02:11 PM|TGirgenti|LINK
Wenushka,
Your suggested change did not work.
I put in a try/catch on the code where it was hanging up. I saw this error:
After Googling that error, I found articles that suggested putting this annotation:
on the Id properties for the ProductApi and Image models.
That allowed me to run the program without getting the hangup and it populated the tables.
I very much appreciate your help in trying to fix this issue.
Thanks,
Tony