0

i use async funcs with await Task.WhenAll inmy function. and some times i get exception with this message "A second operation was started on this context before a previous operation 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".

        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;

    }

this is my functions. getUserOnTimeRequests in on timeRequestService. getCountAsync and GetOnTimeRequestsAsync in timeRequestRepository . and this is my startup code

            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
        );

thanks for your helps.

arman
  • 41
  • 6
  • Does this answer your question? [Entity Framework Core: A second operation started on this context before a previous operation completed](https://stackoverflow.com/questions/48767910/entity-framework-core-a-second-operation-started-on-this-context-before-a-previ) – Camilo Terevinto Sep 24 '21 at 15:48
  • EF Core is not thread-safe, you can't use it like that, you need a new instance in each of the tasks that run in parallel – Camilo Terevinto Sep 24 '21 at 15:49
  • @CamiloTerevinto how can i do that? – arman Sep 24 '21 at 15:54
  • 1
    @arman Hard. You won't be able to use the injected db context, you'd need db context factory or something like that, in order to be able to create db contexts, execute query and dispose afterwards. Simpler is to run the queries sequentially e.g. `count = await ...; values = await ...;` etc. – Ivan Stoev Sep 24 '21 at 16:38
  • async != threaded... it just means that the operations are not blocking a particular thread. Your Task.WhenAll method takes different threaded operations you'd need to call with Task.Run() – pcalkins Sep 24 '21 at 19:48

1 Answers1

0

only when efcore send the SQL command to your database that your LINQ commands has these at the end of you commands like(.tolist or .count or ...) that means LINQ query doesn't load (if you check that type, it is IQueryable), and when you ask it for data by .tolist or .count or ... it will be sent the SQL commands to the database and many of LINQ commands like .remove not async and you cannot use them as async

regestea23
  • 456
  • 6
  • 19