我使用的是EF核心异步方法 - 让背景下,通过内置的DI实体框架核心的异步方法失败
public async Task<bool> Upvote(int userId, int articleId)
{
var article = await context.Articles
.FirstOrDefaultAsync(x => x.Id == articleId);
if (article == null)
{
return false;
}
var existing = await context.Votes
.FirstOrDefaultAsync(x => x.UserId == userId
&& x.ArticleId == articleId);
if (existing != null)
...
这是跑,当有人upvotes的文章。
如果此函数一次只运行一个(一个接一个),一切运行良好。
当我打这个函数多次在同一时间,我得到这个异常:
fail: Microsoft.EntityFrameworkCore.Query.Internal.MySqlQueryCompilationContextFactory[1]
An exception occurred in the database while iterating the results of a query.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable.AsyncEnumerator.<BufferAllAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
断点命中: var existing = await context.Votes.FirstOrDefaultAsync(x => x.UserId == userId && x.ArticleId == articleId);
我也收到此错误:Message [string]:"A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe."
什么是一些可能的解决方案?
编辑1: 这是我怎么设置背景: 在Startup.cs,我配置方面:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ArticlesContext>(options =>
options.UseMySql(Configuration.GetConnectionString("ArticlesDB")));
...
然后我在含的构造函数注入它类:
private ArticlesContext context;
private ILoggingApi loggingApi;
public VoteRepository(ArticlesContext context, ILoggingApi loggingApi)
{
this.context = context;
this.loggingApi = loggingApi;
}
编辑2: 我通过等待一路下跌到控制器:
public async Task<bool> Upvote(int articleId)
{
return await this.votesRepository.Upvote(userId, articleId);
}
然后在控制器...
[HttpPost]
[Route("upvote")]
public async Task<IActionResult> Upvote([FromBody]int articleId)
{
var success = await votesService.Upvote(articleId);
return new ObjectResult(success);
}
编辑3:
我已经改变了我的服务/回购来是短暂的,而不是单身,但我现在m遇到另一个问题:
public int getCurrentUserId()
{
if (!httpContextAccessor.HttpContext.User.HasClaim(c => c.Type == "UserId"))
{
return -1;
}
这是相同的异步问题 - 但这个t ime,HttpContext为null。 我通过
public UserService(IUserRepository userRepository, IHttpContextAccessor httpContextAccessor)
{
this.userRepository = userRepository;
this.httpContextAccessor = httpContextAccessor;
}
回答注入的背景下访问:IHttpContextAccessor需要注册为单身的不是暂时的 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
你能说明你是如何在容器上注册上下文的吗? – Klinger
这感觉就像你在调用异步方法而没有等待它们让它们并行运行? – Pawel
@Klinger我更新了编辑的答案 –