【问题标题】:use entity frame work core in multy thread在多线程中使用实体框架核心
【发布时间】:2021-09-25 01:52:29
【问题描述】:

我在我的函数中使用带有 await Task.WhenAll 的异步函数。 有时我收到此消息的异常“在前一个操作完成之前在此上下文上启动了第二个操作。这通常是由不同的线程同时使用相同的 DbContext 实例引起的。有关如何避免 DbContext 线程问题的更多信息”。

        public async Task<int> getCountAsync(long userId)
    {
        return await _appDbContenxt.onTimeRequests
            .Where(i => (userId == 0 ? true : i.userId == userId))
            .CountAsync()
            ;
    }



        public async Task<List<OnTimeRequest>> GetOnTimeRequestsAsync(int pageSize, int currentPage, long userId)
    {
            return await _appDbContenxt.onTimeRequests
            .Where(i => (userId == 0 ? true : i.userId == userId))
            .OrderByDescending(i => i.id)
            .Skip((currentPage - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync()
            ;
    }

        public async Task<OnTimePaginationDto> getUserOnTimeRequests(int pageSize, int currentPage, long userId)
    {
        Task<int> count = _onTimeRequestsRepository.getCountAsync(userId);
        Task<List<OnTimeRequest>> values = _onTimeRequestsRepository.GetOnTimeRequestsAsync(pageSize, currentPage, userId);
        await Task.WhenAll(count, values);

        OnTimePaginationDto onTimePaginationDto = new OnTimePaginationDto
        {
            count = count.Result,
            values = _mapper.Map<IList<ReadOnTimeRequestDto>>(values.Result)
        };

        return onTimePaginationDto;

    }

这是我的功能。 getUserOnTimeRequests 在 timeRequestService 中。 timeRequestRepository 中的 getCountAsync 和 GetOnTimeRequestsAsync 。 这是我的启动代码

            services.AddScoped<IMemberSheetRepository, MemberShiptRepository>();
        services.AddScoped<IPackageHistoryRepository, PackageHistoryRepository>();
        services.AddScoped<IOnTimeRequestsRepository, OnTimeRequestsRepository>();

        services.AddScoped<IMemberShipService, MemberShipService>();
        services.AddScoped<IPackageHistoryService, PackageHistoryService>();
        services.AddScoped<IOnTimeRequestService, OnTimeRequestService>();


        services.AddDbContext<AppDbContext>(options =>
            options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
        .UseSqlServer(Configuration.GetConnectionString("DbConnection")),ServiceLifetime.Transient
        );

感谢您的帮助。

【问题讨论】:

  • EF Core 不是线程安全的,你不能那样使用它,你需要在每个并行运行的任务中创建一个新实例
  • @CamiloTerevinto 我该怎么做?
  • @arman Hard。您将无法使用注入的数据库上下文,您需要数据库上下文工厂或类似的东西,以便能够创建数据库上下文、执行查询并在之后进行处理。更简单的是按顺序运行查询,例如count = await ...; values = await ...;
  • async != threaded... 这只是意味着操作没有阻塞特定的线程。您的 Task.WhenAll 方法采用不同的线程操作,您需要使用 Task.Run() 调用

标签: asp.net-core entity-framework-core


【解决方案1】:

仅当 efcore 将 SQL 命令发送到您的 LINQ 命令的数据库时 在你的命令末尾有这些,比如(.tolist or .count or ...) 这意味着 LINQ 查询不会加载(如果您检查该类型,它是 IQueryable),并且当您通过 .tolist 或 .count 或...向它询问数据时,它将是 将 SQL 命令发送到数据库和许多 LINQ 命令,如 .remove 不是异步的,你不能将它们用作异步

【讨论】:

    猜你喜欢
    • 2016-08-29
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 2017-10-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多