在申请中,<代码>HomeController在使用背景联合书刊的书章上操作了一部法律,以履行OCR(签字特性确认)。
<代码>HomeController的定义如下:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly BookStoreContext _context;
private readonly IBackgroundJobService _jobService;
public HomeController(ILogger<HomeController> logger, BookStoreContext context, IBackgroundJobService jobService)
{
_context = context;
_logger = logger;
_jobService = jobService;
}
public async Task<IActionResult> RunOCR()
{
await _jobService.RunOCRJob();
return View();
}
}
www.un.org/Depts/DGACM/index_french.htm 班级负责内部监督事务办公室和数据库业务:
public class BackgroundJobService : IBackgroundJobService
{
private readonly ILogger<BackgroundJobService> _logger;
private readonly BookStoreContext _context;
private readonly IFileHandleService _fileService;
private readonly IOcrService _ocrService;
public BackgroundJobService(BookStoreContext context, IOcrService ocrService, ILogger<BackgroundJobService> logger)
{
_logger = logger;
_context = context;
_ocrService = ocrService;
}
public async Task RunOCRJob()
{
_logger.LogInformation("Starting OCR job.");
var toRunOCR = await _context.BookChapters
.Include(b => b.Book)
.Include(t => t.Content)
.Where(c => !c.IsOcrRequested && c.Book.ChapterExtracted)
.OrderBy(o => o.Id)
.Take(20)
.ToListAsync();
var ocrTasks = new List<Task>();
foreach (var chapter in toRunOCR)
{
var bookChapterVm = new ChapterOCRViewModel(chapter.Id, chapter.Path);
ocrTasks.Add(RunBackgroundJob(bookChapterVm));
}
await Task.WhenAll(ocrTasks);
await _context.SaveChangesAsync();
_logger.LogInformation("OCR job completed.");
}
public async Task RunBackgroundJob(ChapterOCRViewModel chapter)
{
try
{
var chapterFilePath = _fileService.GetChapterFilePath(chapter.Path);
var pageContent = await _ocrService.ReadTextFromPdfAsync(chapterFilePath);
var chapterEntity = await _context.BookChapters
.Include(cont => cont.Content)
.FirstOrDefaultAsync(c => c.Id == chapter.Id);
if (chapterEntity.Content == null)
chapterEntity.Content = new ChapterContent();
chapterEntity.Content.Text = pageContent;
chapterEntity.OcrAt = DateTime.UtcNow;
chapterEntity.Status = StatusEnum.ScheduledIndex;
chapterEntity.IsOcrRequested = true;
_logger.LogInformation($"OCR for Chapter ID: {chapter.Id} completed successfully.");
}
catch (Exception ex)
{
_logger.LogError($"Error while OCR for Chapter ID: {chapter.Id}. Error message: {ex.Message}");
}
}
}
我面临的问题是,当我执行《RunOCR行动》时,我遇到以下错误:
fail: Microsoft.EntityFrameworkCore.Query[10100] An exception occurred while iterating over the results of a query for context type OTTT.Db.BookStoreContext . System.InvalidOperationException: A second operation was started on this context instance before a previous operation was completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
我使用了<代码>Take查询,因为查询只给我20个记录,而处理20个记录时,只有2个或3个错误。
我的理解是,这一错误与DbContext的一致意见有关,我怀疑,这可能是利用《书刊》同文的多重背景任务造成的。 我一直在使用依赖性注射来管理DbContext的寿命,但问题依然存在。
I am stuck on how to resolve this concurrency issue and safely use DbContext within my background job.
Edit used the db context factory but got the same error:
public class BackgroundJobService : IBackgroundJobService
{
private readonly IServiceProvider _serviceProvider;
//...
public BackgroundJobService(IDbContextFactory contextFactory, IFileHandleService fileService, BookStoreContext context, IOcrService ocrService,
ILogger<BackgroundJobService> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_context = context;
_fileService = fileService;
_ocrService = ocrService;
_contextFactory = contextFactory;
}
public async Task RunOCRJob()
{
_logger.LogInformation("Starting OCR job.");
using (var context = _contextFactory.Create())
{
var toRunOCR = await context.BookChapters
.Include(b => b.Book)
.Include(t => t.Content)
.Where(c => !c.IsOcrRequested && c.Book.ChapterExtracted)
.OrderBy(o => o.Id)
.Take(20)
.ToListAsync();
//...
await context.SaveChangesAsync();
}
_logger.LogInformation("OCR job completed.");
}
public async Task RunBackgroundJob(BookStoreContext context, ChapterOCRViewModel chapter)
{
try
{
// removed code
var chapterEntity = await context.BookChapters
.Include(cont => cont.Content)
.FirstOrDefaultAsync(c => c.Id == chapter.Id);
// removed code
}
catch (Exception ex)
{
_logger.LogError($"Error while OCR for Chapter ID: {chapter.Id}. Error message: {ex.Message}");
}
}