【发布时间】:2020-02-02 15:21:54
【问题描述】:
我有一个简单的问题,但在任何地方都没有找到答案。
解决方案包含两个 Web API。一个是 .NET Core 2.1 和 EF Core 2.1.1,第二个是 3.1 和 EF Core 3.1.1,我的代码是相同的。有一个自定义存储库和一个控制器。
个人资料库:
public PersonRepository(AppContext appContext)
{
this.appContext = appContext;
}
public async Task<IEnumerable<Person>> GetAll()
{
return await appContext.People.ToListAsync();
}
控制器:
public MyController(PersonRepository personRepository)
{
this.personRepository = personRepository;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var data = personRepository.GetAll();
var data1 = personRepository.GetAll();
var result = await Task.WhenAll(data, data1);
return Ok(data.Result);
}
services.AddDbContext<AppContext>(options => options
.UseSqlServer("")
.EnableSensitiveDataLogging(true));
这似乎是无稽之谈。但这只是为了演示。 我的问题是,为什么这段代码 works 在 2.1 解决方案中但在 3.1 not 并且出现异常 InvalidOperationException:在前一个操作完成之前在此上下文中启动了第二个操作。(对于 IIS 和 Kestrel 也是如此)。
我知道如何在 3.1 中修复它,这不是我的问题。我只需要知道为什么会发生这种情况以及这些版本之间或任何时候发生了什么变化。
非常感谢您的任何回复。
【问题讨论】:
-
我不相信 DbContext 在 EF Core 2 或 3 中是线程安全的。因此,您不应该在
Task.WhenAll的同一上下文中运行两个personRepository.GetAll()任务,因为它们 可以同时运行。您应该async/await2 和 3 中的每个调用。任务调度的问题之一是您不知道它将如何完成。在您的 2 个示例中,这两个任务可能按顺序运行,而在您的 3 个示例中,它们可能同时运行并给您错误。 -
@GrahamKing 感谢您的评论。是的,DBContext 不是线程安全的。所以它可能按照你说的完成,我不知道它是如何完成的(任务调度)。这很有趣,我需要更深入地研究它。
标签: c# .net asp.net-core entity-framework-core asp.net-core-3.1