3

I am trying to create an API backed by mssql and entity framework.

Everything seems to go well until I start to hook up the frontend.

I am getting exceptions saying System.InvalidOperationException: The connection was not closed. The connection's current state is open. or System.InvalidOperationException: Invalid operation. The connection is closed. depending on which API finishes first.

Here is chromes view chrome

I have the following in my startup.cs

services.AddDbContext<ApplicationContext>(opt => {
    opt.UseSqlServer(new SqlConnection(Configuration["CONNECTIONSTRINGS_AZURECONNECTION"]), builder => builder.MigrationsAssembly("Application.Web"));
    opt.UseOpenIddict();
});

services.AddIdentity<User, Role>()
    .AddEntityFrameworkStores<ApplicationContext, Guid>()
    .AddDefaultTokenProviders();

All of my repositories are scoped

services.AddScoped<INotificationRepository, NotificationRepository>();

And so is the database context

services.AddScoped<ApplicationContext, ApplicationContext>();

Both controllers are basically the same

private readonly INotificationRepository _notificationRepository;

public NotificationsController(UserManager<User> userManager, INotificationRepository notificationRepository)
    :base(userManager)
{
    _notificationRepository = notificationRepository;
}

[HttpGet]
public async Task<IActionResult> GetAsync()
{
    var user = await GetCurrentUserAsync();
    return new OkObjectResult(await _notificationRepository.FindByAsync(n => n.User == user));
}

Am I correct in thinking that the context needs to be scoped per request? And each chrome call is a separate request which would create a separate scope?

So each call would basically be:

  1. Request

  2. Auth filters

  3. Controller

  4. async function

  5. async get current user -> return user (dont destroy context)

  6. async repository function

  7. return from repository

  8. return from controller

Google is no help so I assume I am doing something incorrectly :)

Lee
  • 1,096
  • 2
  • 20
  • 33

1 Answers1

4

Turns out it was this line:

opt.UseSqlServer(new SqlConnection(Configuration["CONNECTIONSTRINGS_AZURECONNECTION"]), builder => builder.MigrationsAssembly("Application.Web"));

Once I changed it to this everything works as expected

opt.UseSqlServer(Configuration["CONNECTIONSTRINGS_AZURECONNECTION"], builder => builder.MigrationsAssembly("Application.Web"));
Lee
  • 1,096
  • 2
  • 20
  • 33
  • Passing SqlConnection haven't solved my case, but helped me to have more details to solve the problem. Solved using this solution https://stackoverflow.com/questions/55543595/cannot-access-a-disposed-object-a-common-cause-of-this-error-is-disposing-a-con – Murilo Maciel Curti May 19 '22 at 00:24