我使用的是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我更新了編輯的答案 –