EF Core调用EntityState.Modified,然后发出异步http请求以处理数据库上下文

时间:2018-07-22 01:31:44

标签: c# dependency-injection .net-core ef-core-2.1

导致问题的代码

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();

db上下文已添加到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循环中使用db上下文/修改并保存了代码前面的行,确定了!

编辑:我不是说我对异步HTTP请求感到抱歉!

TL; DR,

似乎问题与线程被处理有关,我可以使用非异步的http req,我希望能够尽可能保持这种方式,因为http请求需要一段时间才能完成。

谢谢您的光临,有什么想法吗?

1 个答案:

答案 0 :(得分:1)

删除GetRndUserAgent()中的usings语句,这将处理数据库上下文!!!

    using (_animaldb)
    {
        userAgent = await _animaldb.UserAgents.FindAsync(id);

    }