EF Core 调用 EntityState.Modified 然后发出异步 http 请求处理数据库上下文
EF Core calling EntityState.Modified then making async http request disposing db context
导致问题的代码
var cats= await _animaldb.Cats.ToListAsync<Cats>();
foreach (var kitty in cats)
{
kitty.LastReq = DateTime.Now;
kitty.DailyReqCount = cats.DailyReqCount + 1;
// make HTTP request here to some endpoint async
var data = await _restOps.GetJsonAsync("url");
// perhaps thread is being disposed ?
_animaldb.Entry(kitty).State = EntityState.Modified;// err 2nd iteration
}
_animaldb.SaveChanges();
数据库上下文添加到 startup.cs
services.AddDbContext<AnimalDBContext>(options => options.UseSqlServer(connection));
编辑:添加 getJsonAsyn
public class RestOps
{
private readonly ILogger<RestOps> _logger;
private readonly Animaldb _animaldb;
public RestOps(ILogger<RestOps> logger, Animaldb animaldb)
{
_logger = logger;
_animaldb= animaldb;
}
public async Task<string> GetJsonAsync(string url, bool randomUserAgent = false)
{
var httpClientHandler = new HttpClientHandler();
var client = new HttpClient(httpClientHandler);
client.Timeout = TimeSpan.FromMilliseconds(3000);
UserAgents userAgent = await GetRndUserAgent();
var userAgentStr = string.Empty;
var resultUserAgent = randomUserAgent ? userAgentStr = userAgent.Name : userAgentStr = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36";
client.DefaultRequestHeaders.Add("User-Agent", resultUserAgent);
// Make a list of web addresses.
// GetAsync returns a Task<HttpResponseMessage>.
string content = null;
try
{
HttpResponseMessage response = await client.GetAsync(url);
// Retrieve the website contents from the HttpResponseMessage.
content = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
content = "Failed to get:" + url;
}
return content;
}
private async Task<UserAgents> GetRndUserAgent()
{
UserAgents userAgent = null;
Random r = new Random();
var id = r.Next(0, 40);
using (_animaldb)
{
userAgent = await _animaldb.UserAgents.FindAsync(id);
}
return userAgent;
}
}
错误信息:
Cannot access a disposed object. A common cause of this error is disposing a
context that was resolved from dependency injection and then later trying to
use the same context instance elsewhere in your application. This may occur
if you are calling Dispose() on the context, or wrapping the context in a
using statement. If you are using dependency injection, you should let the
dependency injection container take care of disposing context instances
注意:我在 for 循环中使用数据库上下文/修改并保存条目,好的,在代码的前面!
编辑:我没有说我正在制作异步 http 请求抱歉!
TL;DR,
问题似乎与处理线程有关,我可以使用非异步 http 请求,我希望尽可能保持这种方式,因为 http 请求需要一段时间才能完成。
感谢您的关注,有什么想法吗?
去掉GetRndUserAgent()中的usings语句,这是对db上下文的处理!!!
using (_animaldb)
{
userAgent = await _animaldb.UserAgents.FindAsync(id);
}
导致问题的代码
var cats= await _animaldb.Cats.ToListAsync<Cats>();
foreach (var kitty in cats)
{
kitty.LastReq = DateTime.Now;
kitty.DailyReqCount = cats.DailyReqCount + 1;
// make HTTP request here to some endpoint async
var data = await _restOps.GetJsonAsync("url");
// perhaps thread is being disposed ?
_animaldb.Entry(kitty).State = EntityState.Modified;// err 2nd iteration
}
_animaldb.SaveChanges();
数据库上下文添加到 startup.cs
services.AddDbContext<AnimalDBContext>(options => options.UseSqlServer(connection));
编辑:添加 getJsonAsyn
public class RestOps
{
private readonly ILogger<RestOps> _logger;
private readonly Animaldb _animaldb;
public RestOps(ILogger<RestOps> logger, Animaldb animaldb)
{
_logger = logger;
_animaldb= animaldb;
}
public async Task<string> GetJsonAsync(string url, bool randomUserAgent = false)
{
var httpClientHandler = new HttpClientHandler();
var client = new HttpClient(httpClientHandler);
client.Timeout = TimeSpan.FromMilliseconds(3000);
UserAgents userAgent = await GetRndUserAgent();
var userAgentStr = string.Empty;
var resultUserAgent = randomUserAgent ? userAgentStr = userAgent.Name : userAgentStr = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36";
client.DefaultRequestHeaders.Add("User-Agent", resultUserAgent);
// Make a list of web addresses.
// GetAsync returns a Task<HttpResponseMessage>.
string content = null;
try
{
HttpResponseMessage response = await client.GetAsync(url);
// Retrieve the website contents from the HttpResponseMessage.
content = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
content = "Failed to get:" + url;
}
return content;
}
private async Task<UserAgents> GetRndUserAgent()
{
UserAgents userAgent = null;
Random r = new Random();
var id = r.Next(0, 40);
using (_animaldb)
{
userAgent = await _animaldb.UserAgents.FindAsync(id);
}
return userAgent;
}
}
错误信息:
Cannot access a disposed object. A common cause of this error is disposing a
context that was resolved from dependency injection and then later trying to
use the same context instance elsewhere in your application. This may occur
if you are calling Dispose() on the context, or wrapping the context in a
using statement. If you are using dependency injection, you should let the
dependency injection container take care of disposing context instances
注意:我在 for 循环中使用数据库上下文/修改并保存条目,好的,在代码的前面!
编辑:我没有说我正在制作异步 http 请求抱歉!
TL;DR,
问题似乎与处理线程有关,我可以使用非异步 http 请求,我希望尽可能保持这种方式,因为 http 请求需要一段时间才能完成。
感谢您的关注,有什么想法吗?
去掉GetRndUserAgent()中的usings语句,这是对db上下文的处理!!!
using (_animaldb)
{
userAgent = await _animaldb.UserAgents.FindAsync(id);
}