I catch exception in my API. This is code of service, when I am calling any methods of any repositories apart from selectAll() method I catch such mistake. Also, I catch this exception when I use LINQ with SelectAll() object.

using Journal.DAL.Interfaces;
using Journal.Domain.Models;
using Journal.Domain.Responses;
using Journal.Domain.JsonModels;
using Journal.Service.Interfaces;
using Journal.Domain.ResponseModels;

namespace Journal.Service.Implementations
{
    public class MTAccountService : IMTAccountService
    {
        private readonly IMTAccountRepository _mtAccountRepository;
        private readonly IUserRepository _userRepository;
        private readonly IMTDataRepository _mtDataRepository;

        public MTAccountService(IMTAccountRepository mtAccountRepository, IUserRepository userRepository, IMTDataRepository mtDataRepository)
        {
            _mtAccountRepository = mtAccountRepository;
            _userRepository = userRepository;
            _mtDataRepository = mtDataRepository;
        }

        public async Task<BaseResponse<MTAccountResponseModel>> AddAccount(MTAccountJsonModel accountModel)
        {
            var response = new BaseResponse<MTAccountResponseModel>();
            try
            {
                var accounts = await _mtAccountRepository.SelectAll();
                if (accounts.FirstOrDefault(x => x.Login == accountModel.Login) != null)
                {
                    response.StatusCode = Domain.Enums.StatusCode.ERROR;
                    response.Message = "Account exists";
                    return response;
                }
                if (!await _mtDataRepository.Initialize(accountModel))
                {
                    response.StatusCode = Domain.Enums.StatusCode.ERROR;
                    response.Message = "Account initializing error";
                    return response;
                }
                    var account = new MTAccount();

                account.Id = Guid.NewGuid();
                account.Login = accountModel.Login;
                account.Password = accountModel.Password;
                account.Server = accountModel.Server;
                account.UserId = accountModel.UserId;
                var users = await _userRepository.SelectAll();
                account.User = users.FirstOrDefault(x => x.Id == accountModel.UserId);

                if (await _mtAccountRepository.Create(account))
                    {
                        response.StatusCode = Domain.Enums.StatusCode.OK;
                        response.Data = new MTAccountResponseModel(account);
                    }
                    else
                    {
                        response.StatusCode = Domain.Enums.StatusCode.ERROR;
                        response.Message = "DB Error";
                    }

            }
            catch(Exception ex) 
            { 
                response.StatusCode=Domain.Enums.StatusCode.ERROR;
                response.Message=ex.Message;
            }
            return response;
        }

        public async Task<BaseResponse<bool>> DeleteMTAccount(Guid accountId)
        {
            var response = new BaseResponse<bool>();
            try
            {
                var accounts = await _mtAccountRepository.SelectAll();
                var account = accounts.FirstOrDefault(x => x.Id == accountId);
                if(account == null)
                {
                    response.Data = false;
                    response.StatusCode = Domain.Enums.StatusCode.ERROR;
                    response.Message = "Account with such Id does not exists";
                }
                else
                {
                    if(await _mtAccountRepository.Delete(account))
                    {
                        response.Data = true;
                        response.StatusCode = Domain.Enums.StatusCode.OK;
                        
                    }
                    else
                    {
                        response.Data = false;
                        response.StatusCode = Domain.Enums.StatusCode.ERROR;
                        response.Message = "DB error";
                    }
                }
            }
            catch (Exception ex)
            {
                response.Data = false;
                response.StatusCode = Domain.Enums.StatusCode.ERROR;
                response.Message = ex.Message;
            }
            return response;
        }
    }
}

This is repository, that place when exception occures. It says that ApplicationDbContext variable was disposed

using Journal.DAL;
using Journal.DAL.Interfaces;
using Journal.Domain.Models;

namespace Journal.DAL.Repositories
{
    public class MTAccountRepository : IMTAccountRepository
    {
        private readonly ApplicationDbContext _db;
        public MTAccountRepository(ApplicationDbContext db)
        {
            _db = db;
        }

        public async Task<bool> Create(MTAccount entity)
        {
            await _db.MTAccounts.AddAsync(entity);
            await  _db.SaveChangesAsync();
            return true;
        }

        public async Task<bool> Delete(MTAccount entity)
        {
            _db.MTAccounts.Remove(entity);
            await _db.SaveChangesAsync();
            return true;
        }

        public async Task<bool> Edit(MTAccount entity)
        {
            _db.MTAccounts.Update(entity);
            await _db.SaveChangesAsync();
            return true;
        }

        public async Task<IQueryable<MTAccount>> SelectAll()
        {
            return await Task.FromResult(_db.MTAccounts);
        }
    }
}

This is builder

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var connection = builder.Configuration.GetConnectionString("DefaultConnection");

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connection), optionsLifetime: ServiceLifetime.Singleton);

builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IMTAccountRepository, MTAccountRepository>();
builder.Services.AddScoped<ISubscriptionRepository, SubscriptionRepository>();
builder.Services.AddScoped<IMTDataRepository, MTDataRepository>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IMTAccountService, MTAccountService>();
builder.Services.AddScoped<IMTDataService, MTDataService>();
builder.Services.AddScoped<ISubscriptionService, SubscriptionService>();
builder.Services.AddScoped<IMTDealRepository, MTDealRepository>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();


app.MapControllers();

app.Run();

I tried all possible solutions from Internet. Using different lifetime options and using sync instead of async methods.

1

There are 1 best solutions below

3
Svyatoslav Danyliv On

Returning IQueryable from async method has no sense. There is no database request. It is query ready for execution.

Make this method synchronous:

public IQueryable<MTAccount> SelectAll()
{
    return _db.MTAccounts;
}

Also use await FirstOrDefaultAsync - it is real database call.

Make this change and analyse where you store IQueryable. Enumerating IQueryable returned by context, which disposed before enumeration, throws this exception.