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.
Returning
IQueryablefrom async method has no sense. There is no database request. It is query ready for execution.Make this method synchronous:
Also use
await FirstOrDefaultAsync- it is real database call.Make this change and analyse where you store
IQueryable. EnumeratingIQueryablereturned by context, which disposed before enumeration, throws this exception.