I have a View, which causes an exception occasionally. While retrieving the initial data from the db, sometimes it fails with an ObjectDisposedException for IServiceProvider.
We are not using the type IServiceProvider directly anywhere, but EF Core is using it, since the dependent services are registered.
A new DbContext gets created per operation. What is special here, is that one db operation starts another db method to get more data to append it to the model.
This is the code:
Program.cs:
var builder = WebApplication.CreateBuilder(args);builder.Services.AddDbContextFactory<MyDbContext>(options => options.UseSqlServer( builder.Configuration.GetConnectionString("db"), sqlServerOptions => sqlServerOptions.CommandTimeout(5)), ServiceLifetime.Transient);builder.Services.AddRazorPages();builder.Services.AddServerSideBlazor();builder.Services.AddScoped<LoadDataPort, LoadPurchaseService>();[...]DataView.razor.cs:
public partial class DataView : MyComponentBase, IDisposable{ [Inject] private LoadDataPort LoadDataPort { get; set; } = default!; protected override async Task OnInitializedAsync() { var purchases = await LoadDataPort.GetAllPurchases(); }}LoadPurchaseService:
public class LoadPurchaseService : LoadDataPort{ public async Task<List<Purchase>> GetAllPurchases() { using MyDbContext dbContext = contextFactory.CreateDbContext(); List<Purchase> purchases = await dbContext.Purchase .Include(purchase => purchase.Status) .AsNoTracking() .OrderByDescending(n => n.SomeId) .AsSplitQuery() .TagWithCallSite() .TagWith("GetAllPurchases") .ToListAsync(); await LoadCategoriesAsync(purchases); return purchases; } private async Task LoadCategoriesAsync(List<Purchase> purchases) { List<PurchaseCategory> allCategories = await GetAllCategoriesAsync(); purchases.ForEach(purchase => { List<PurchaseCategory> list = purchase.CategoriesIds .Where(catId => allCategories.Any(cat => cat.Id == catId)) .Select(catId => allCategories.First(cat => cat.Id == catId)) .ToList(); purchase.Categories = list; }); } public async Task<List<PurchaseCategory>> GetAllCategoriesAsync() { using MyDbContext dbContext = contextFactory.CreateDbContext(); return await dbContext.PurchaseCategory.AsNoTracking() .OrderBy(category => category.Id) .ToListAsync(); }}This throws this exception:
Unhandled exception in circuit '"xTAHc5qVVFdxpnRUv49FLQCdLHDcvwG_4Kdble8NGwg"'.System.ObjectDisposedException: Cannot access a disposed object.Object name: 'IServiceProvider'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()[...] at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsNoTracking[TEntity](IQueryable`1source) at LoadPurchaseService.GetAllCategoriesAsync() in D:\source\Services\Purchase\LoadPurchaseService.cs:line 169 at LoadPurchaseService.LoadCategoriesAsync(List`1 purchases) in D:\source\Services\Purchase\LoadPurchaseService.cs:line 151 at LoadPurchaseService.GetAllPurchasesAsync() in D:\source\Services\Purchase\LoadPurchaseService.cs:line 44 at Purchases.OnInitializedAsync() in D:\source\Pages\Purchases.razor.cs:line 61 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(TasktaskToHandle, ComponentState owningComponentState)
I am not sure what is causing this, since I cannot reproduce the error myself. I found it in our logs a few times.It also happens rather rarely, but I would like to fix it.