C# 将异步webrequest与数据库检索叠加

C# 将异步webrequest与数据库检索叠加,c#,entity-framework,asynchronous,httpwebrequest,task-parallel-library,C#,Entity Framework,Asynchronous,Httpwebrequest,Task Parallel Library,在我目前正在构建的系统中,我必须向提供计算服务的API发出webrequests。此服务需要一组复杂的参数,我必须从数据库中检索这些参数。目前,我使用实体框架来检索这些实体,对于每个实体,我向这个api发出请求,检索结果,最后将所有结果保存到数据库(所有操作都是同步完成的) 当实体集增加时,这种方法会出现缩放问题(因为我必须每30分钟对每个实体调用一次计算服务)。因此,我希望以并行(或异步)方式对实体进行数据库检索和web请求,并对其他实体执行相同的操作。(不是为了减少数据加载时间,而是为了在等

在我目前正在构建的系统中,我必须向提供计算服务的API发出webrequests。此服务需要一组复杂的参数,我必须从数据库中检索这些参数。目前,我使用实体框架来检索这些实体,对于每个实体,我向这个api发出请求,检索结果,最后将所有结果保存到数据库(所有操作都是同步完成的)

当实体集增加时,这种方法会出现缩放问题(因为我必须每30分钟对每个实体调用一次计算服务)。因此,我希望以并行(或异步)方式对实体进行数据库检索和web请求,并对其他实体执行相同的操作。(不是为了减少数据加载时间,而是为了在等待webrequest完成时完成工作)

既然EF5上下文不是线程安全的,那么我实现这一点的最佳选择是什么?我应该编写特定的SQL查询,使用LINQ等吗?有没有人有类似方法的代码示例(并行方式下webrequest的db检索)

编辑 添加一个小代码示例(非常简化)。假设对webservice的调用可能需要几秒钟,这将无法扩展

foreach(entityId in entityIds)
{
    var entity = _repository.Find(entityId);
    _repository.LoadData(entity);
    _validator.ValidateData(entity);
    var result = _webservice.Call(entity);
    entity.State = result.State;
}

_repository.SaveChanges();

您可以使用生产者-消费者体系结构:一个线程访问数据库并将数据添加到类似于
BlockingCollection
的内容中。另一个线程(或多个线程)从集合中读取数据并执行web请求。

您可以使用生产者-消费者体系结构:一个线程访问数据库并将数据添加到类似于
BlockingCollection
的内容中。另一个线程(或多个线程)从集合中读取数据并执行web请求。

有不同的方法可用于并行化。这完全取决于你真正想要/需要什么

一种方法是使用一个


您可以通过不同的方式来并行处理此问题。这完全取决于你真正想要/需要什么

一种方法是使用一个


你好抱歉,这可能是个愚蠢的问题,但使用单个线程进行数据检索意味着我可以继续使用EF读取数据?如果是这样的话,我想我也可以使用相同的模式来保存web请求的结果?@user842077是的,这就是这种方法的要点,您可以继续使用非线程安全的类型。抱歉,这可能是个愚蠢的问题,但使用单个线程进行数据检索意味着我可以继续使用EF读取数据?如果是这样,我想我也可以使用相同的模式保存web请求的结果?@user842077是的,这就是这种方法的要点,您可以继续使用非线程安全的类型。您仍然可以在调用数据库时对web服务进行异步调用。或者使用Task.Run调用数据库(如果需要)。你能为你想做的事情提供一些代码吗?添加了一个小示例。你也可以使用SaveAsync()方法…嗯。。SaveAsync()是EF 6中即将推出的功能,对吗?您仍然可以在调用数据库时对web服务进行异步调用。或者使用Task.Run调用数据库(如果需要)。你能为你想做的事情提供一些代码吗?添加了一个小示例。你也可以使用SaveAsync()方法…嗯。。SaveAsync()是EF 6中即将推出的功能,对吗?实体框架上下文不是线程安全的。由于这个原因,我无法并行检索数据。我没有意识到这一点。我不是EF专家。那么,你打算怎么做呢?EntityID有多少个ID?每个实体的大小是多少?一种方法是检索所有实体,然后并行化对web服务的调用。这行吗?我认为斯维克提供的答案是正确的。另一种选择是扔掉EF,按照你的方法去做。扔掉EF不会让你走多远,因为我认为你不能使用相同的db连接实例。与使用多个EF上下文几乎相同。我想知道如果EF上下文不跟踪更改,它是否是线程安全的。实体框架上下文不是线程安全的。由于这个原因,我无法并行检索数据。我没有意识到这一点。我不是EF专家。那么,你打算怎么做呢?EntityID有多少个ID?每个实体的大小是多少?一种方法是检索所有实体,然后并行化对web服务的调用。这行吗?我认为斯维克提供的答案是正确的。另一种选择是扔掉EF,按照你的方法去做。扔掉EF不会让你走多远,因为我认为你不能使用相同的db连接实例。与使用多个EF上下文几乎相同。我想知道如果EF上下文不跟踪更改,它是否是线程安全的。
Parallel.ForEach(
    entityIds,
    entityId =>
    {
        var entity = _repository.Find(entityId);
        _repository.LoadData(entity);
        _validator.ValidateData(entity);
        var result = _webservice.Call(entity);
        entity.State = result.State;
    });

_repository.SaveChanges();