Ядро EF: вторая операция, запущенная в этом контексте до завершения предыдущей операции

#c# #.net-core #entity-framework-core

#c# #.net-ядро #entity-framework-core

Вопрос:

Я ценю, что этот вопрос был задан. Но я, кажется, сделал то, что люди предлагают, чтобы исправить это, и у меня все еще та же проблема. Я не вижу, где я ошибаюсь. Мы были бы очень признательны за любую помощь.

Я получаю следующую ошибку:

Исключение InvalidOperationException: вторая операция, запущенная в этом контексте до завершения предыдущей операции. Обычно это вызвано тем, что разные потоки используют один и тот же экземпляр DbContext

В этих конкретных областях:

 return await _dbContext.Set<T>().FindAsync(id);
var editPost = await _postRepository.GetByIdAsync(postModel.Id); 
await _postAppService.Update(mapped);
await _postPageService.UpdatePost(Post);
  

Вот мой код:

Просто чтобы добавить немного больше деталей. Я перечислю точные шаги:

Сначала я выбираю запись, которую хотел бы отредактировать. Вызывается следующее:

 public async Task<IActionResult> OnGetAsync(int? postId)
        {
            if (postId == null)
            {
                return NotFound();
            }

            Post = await _postPageService.GetPostById(postId.Value);
            if (Post == null)
            {
                return NotFound();
            }                   
            return Page();
        }

public async Task<PostViewModel> GetPostById(int postId)
        {
            var post = await _postAppService.GetPostById(postId);
            
            var mapped = _mapper.Map<PostViewModel>(post);

            return mapped;
        }

public async Task<PostModel> GetPostById(int postId)
        {
            var post = await _postRepository.GetByIdAsync(postId);
            var mapped = ObjectMapper.Mapper.Map<PostModel>(post);
            return  mapped;
        }



  public virtual async Task<T> GetByIdAsync(int id)
        {
            return await _dbContext.Set<T>().FindAsync(id);
        }
  

Затем я вношу свои изменения и нажимаю кнопку обновить:

 public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
        try
    {
        await _postPageService.UpdatePost(Post);
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!PostExists(Post.Id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return RedirectToPage("./Index");
}

public async Task UpdatePost(PostViewModel postViewModel)
{        
    var mapped = _mapper.Map<PostModel>(postViewModel);
    
    if (mapped == null)
        throw new Exception($"Entity could not be mapped.");
        await _postAppService.Update(mapped);
    _logger.LogInformation($"Entity successfully added - IndexPageService");
}

public async Task Update(PostModel postModel)
{
    ValidatePostIfNotExist(postModel);
        var editPost = await _postRepository.GetByIdAsync(postModel.Id);
    if (editPost == null)
        throw new ApplicationException($"Entity could not be loaded.");
        ObjectMapper.Mapper.Map<PostModel, Post>(postModel, editPost);
        await _postRepository.UpdateAsync(editPost);
    _logger.LogInformation($"Entity successfully updated - AspnetRunAppService");
}

public async Task UpdateAsync(T entity)
{
    _dbContext.Entry(entity).State = EntityState.Modified;
    await _dbContext.SaveChangesAsync();
}
  

Я также установил время жизни my DbContext равным Transient .

 services.AddDbContext<MyJourneyContext>(c => c.UseSqlServer(_config.GetConnectionString("MyJourneyConnectionString")),
                                        ServiceLifetime.Transient);
  

Итак, я использую await и установил время жизни my DbContext равным Transient . Но я явно все еще делаю что-то не так. Кто-нибудь может мне помочь с этим?

Комментарии:

1. Вы должны использовать ограниченное время жизни. Переходное время жизни создает новый Databasecontext при каждом его вызове, но ограниченное время жизни создает Databasecontext для http-запроса.

2. Вы имеете в виду следующее: сервисы. Добавьте DbContext<MyJourneyContext>(c => c.UseSqlServer(_config. GetConnectionString(«MyJourneyConnectionString»)), ServiceLifetime. Область действия); Я все еще получаю ту же ошибку

3. AddDbContext по умолчанию использует Scoped, что обычно является лучшим выбором, но использование Transient также должно работать и не вызовет этой ошибки. Здесь недостаточно информации, чтобы указать, где вы используете экземпляр DbContext из нескольких потоков. Попробуйте упростить сценарий до такой степени, чтобы вы могли опубликовать полное воспроизведение.

4. Привет, Дэвид, я добавил немного больше деталей, перечислив предпринятые мной шаги, которые привели к ошибке. Помогает ли это как-нибудь?

5. Возможно, вы можете определить, в какой момент выдается ошибка? Она генерируется при сохранении записи или при получении записи? поскольку на основе методов, которые вы предоставили выше, не существует ни одного метода, в котором вы обычно выполняете две операции в рамках одного метода. Также стоит отметить, что неасинхронные методы (не возвращающие задачи) не обрабатываются асинхронно, даже если вы вызываете их с помощью await при их вызове.