Hi everyone. I'm learning EF Core 8 and encountered some issues with pagination in the following code.
using Dashboard.Data; using Dashboard.Data.Models; using JetBrains.Annotations; using MediatR; using Microsoft.EntityFrameworkCore; using Shared.Utils; namespace Dashboard.Core.Advertising.Api; [UsedImplicitly] public class ListAdvertisersQuery : PaginationQuery, IRequest<PaginationResult<Advertiser>> { public bool WithCampaigns { get; set; } } [UsedImplicitly] public class ListAdvertisersQueryHandler(DataContext dataContext) : IRequestHandler<ListAdvertisersQuery, PaginationResult<Advertiser>> { public async Task<PaginationResult<Advertiser>> Handle(ListAdvertisersQuery query, CancellationToken cancellationToken) { var queryable = dataContext.Advertisers.AsQueryable(); if (query.WithCampaigns) { queryable = queryable.Include(x => x.Campaigns); } var totalItemsTask = queryable.CountAsync(cancellationToken); var resultTask = queryable.Take(query.Limit).ToListAsync(cancellationToken); await Task.WhenAll(resultTask, totalItemsTask); return PaginationResult<Advertiser>.From(resultTask.Result, totalItemsTask.Result, query); } }
When I run this code multiple times, I encounter an error.
System.InvalidOperationException: A second operation was started on this context instance 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, see https://go.microsoft.com/fwlink/?linkid=2097913.
DataContext is registered in DI like this
builder.Services.AddDbContext<DataContext>(options => { var databaseConfiguration = builder.Configuration.GetSection(DatabaseConfiguration.SectionName).Get<DatabaseConfiguration>(); options .UseNpgsql(databaseConfiguration!.ConnectionString) .UseSnakeCaseNamingConvention(); });
I don't want to await every query sequentially. Could you help me with it and explain how to run it in parallel?
Top comments (6)
Okay, I've found a solution. I can use IDbContextFactory.
learn.microsoft.com/en-us/ef/core/...
Register in DI
Using
Did this fit your exact use case?
You can't use
await Task.WhenAll()
, do this:var totalItems = await queryable.CountAsync(cancellationToken);
var result = await queryable.Take(query.Limit).ToListAsync(cancellationToken);
return PaginationResult<Advertiser>.From(result, totalItems, query);
Got it. Is there a way to run it independently? My dataset is quite large, so running queries sequentially is slow.
If you have a high load on your server, start implementing caching: github.com/VahidN/EFCoreSecondLeve...
Hi, Atmosphere ,
Thanks for sharing
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more