No se puede acceder a una instancia de contexto dispuesta

Mi aplicación: .Net Core 3.1 Aplicación web utilizando la arquitectura de Microservicio; Identidad para Autorización & Authentication como API de Microservicio independiente.

He ampliado la tabla AspNetUsers y AspNetRoles con campos personalizados. Conseguir el siguiente error cuando estoy tratando de crear un nuevo rol usando el RoleManager de identidad.

No se puede acceder a una instancia de contexto dispuesta. Una causa común de esto error está desechando una instancia contextual que se resolvió la inyección de dependencia y luego intentar utilizar el mismo contexto instancia en otro lugar de su solicitud. Esto puede ocurrir si usted es llamando 'Dispose' en la instancia contextual, o envolviéndolo en un uso declaración. Si usted está usando la inyección de dependencia, debe dejar la contenedor de inyección de dependencia se ocupa de la eliminación de contexto casos. Nombre del objeto: 'MembershipDBContext'.

Encontrar mi código abajo

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            var idenConnectionString = Configuration["DbContextSettings:IdentityConnectionString"];
            var userConnectionString = Configuration["DbContextSettings:UserConnectionString"];
            var dbPassword = Configuration["DbContextSettings:DbPassword"];
            var builder = new NpgsqlConnectionStringBuilder(idenConnectionString)
            {
                Password = dbPassword
            };
            var userBuilder = new NpgsqlConnectionStringBuilder(userConnectionString)
            {
                Password = dbPassword
            };

            services.AddDbContext(opts => opts.UseNpgsql(builder.ConnectionString));
            services.AddDbContext(opts => opts.UseNpgsql(userBuilder.ConnectionString));

            

            services.AddIdentity(options =>
            {
                options.Password.RequiredLength = 8;
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+ ";
                options.SignIn.RequireConfirmedEmail = false;
            }).AddRoles().AddEntityFrameworkStores()
            .AddDefaultTokenProviders();


            services.AddTransient();//IdentityMS
            services.AddTransient();//IdentityMS

            services.AddTransient();//IdentityMS
            services.AddTransient();//IdentityMS
            services.AddTransient();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
            
            services.AddMediatR(typeof(Startup));
            RegisterServices(services);
        }

MiembrosDBContext.cs

    public class MembershipDBContext : IdentityDbContext
    {
        public MembershipDBContext(DbContextOptions options) : base(options)
        {
        }
    }

AdministraciónController

 public class AdministrationController : Controller
    {
        private readonly IAdministrationMVCService _adminService;

        public AdministrationController(IAdministrationMVCService adminService)
        {
            _adminService = adminService;            
        }

        // GET: AdministrationController/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: AdministrationController/Create
        [HttpPost]
        //[ValidateAntiForgeryToken]
        public async Task CreateAsync(MembershipRole rm)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    rm.CompanyId = 1;
                    await _adminService.AddRoles(rm);
                    //return RedirectToAction(nameof(Index));
                    return View();
                }
                catch
                {
                    return View();
                }
            }
            return View();
        }

      
    }

AdministrationApiController

[HttpPost]
        public void Post([FromBody] MembershipRole role)
        {
            _adminMSService.AddRoles(role);
        }

AdministraciónRepositorio

public class AdministrationRepository : IAdministrationRepository
    {
        private readonly RoleManager _roleManager;
        private readonly UserManager _userManager;

        public AdministrationRepository(RoleManager roleManager, UserManager userManager)
        {            
            _roleManager = roleManager;
            _userManager = userManager;
        }

        public async Task AddRolesAsync(MembershipRole rvm)
        {
            try
            {
                IdentityResult result = await _roleManager.CreateAsync(rvm);
                if (result.Succeeded) {

                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

    }

Traté de hacer los servicios y repositorios como singleton pero tampoco funcionó. ¿Qué estoy perdiendo aquí? ¿Alguna idea?

Pregunta hecha hace 3 años, 4 meses, 27 días - Por pixelpioneer


3 Respuestas:

  • ¡Resolvió el tema! Como DavidG señaló en su comentario, perdí la palabra clave 'espera' en ciertos lugares como AdministraciónApiController. Posting as an 'Answer' here, as I am unable to mark the comment as 'Answer'.

    Respondida el Dec 18, 2020 a las 11:40 - por syntaxsensei8acf

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando "No se puede acceder a una instancia de contexto dispuesta" en .NET Core generalmente se produce cuando se intenta acceder a un contexto de base de datos después de que el mismo haya sido liberado o eliminado. Esto puede suceder si se hace uso incorrecto de la inyección de dependencias o si se está intentando acceder a un contexto que ya ha sido desechado.

    En tu caso, parece que el error está relacionado con la clase MembershipDBContext, la cual es el contexto de tu base de datos. Al registrar tus DbContext en el método ConfigureServices de tu clase Startup.cs, estás configurando la inyección de dependencias para que el contenedor de IoC se encargue de la creación y eliminación de instancias de DbContext. Sin embargo, podrías estar teniendo un problema en la forma en que se está utilizando el contexto en tus servicios y repositorios.

    Algunas recomendaciones para solucionar este problema:

    • Asegúrate de no estar utilizando `Dispose` manualmente en el DbContext en ningún lugar de tu código. El contenedor de IoC debe encargarse de la gestión de ciclos de vida de las instancias.
    • Verifica que no estés utilizando contextos desechados en tus servicios o repositorios. Por ejemplo, en el `AdministrationRepository`, asegúrate de que la instancia `_roleManager` y `_userManager` provengan de servicios y no sean eliminados manualmente.
    • Considera la posibilidad de utilizar scopes de DbContext para limitar el tiempo de vida de una instancia del contexto a la duración de una solicitud. Esto se puede lograr configurando un DbContext como Scoped en el método `ConfigureServices`.

    Por ejemplo:

    csharp
    services.AddDbContext(opts => opts.UseNpgsql(builder.ConnectionString), ServiceLifetime.Scoped);
    
    • Revisa la gestión de contexto en tu repositorio y servicios. Asegúrate de que los contextos sean correctamente recibidos y utilizados en el ámbito de una solicitud.

    Espero que estas recomendaciones te ayuden a resolver el problema con el error "No se puede acceder a una instancia de contexto dispuesta" en tu aplicación .NET Core. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 19, 2020 a las 11:40 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error que recibes indica que estás intentando acceder a una instancia de contexto desechada. Esto ocurre cuando se elimina una instancia de contexto que se resolvió mediante inyección de dependencias y luego se intenta utilizar la misma instancia de contexto en otro lugar de la solicitud.

    En tu código, estás utilizando el patrón de repositorio para acceder a la base de datos. El repositorio se inyecta como una dependencia en el controlador. Sin embargo, el repositorio no está registrado como un singleton en el contenedor de inyección de dependencias. Esto significa que se crea una nueva instancia del repositorio cada vez que se resuelve.

    Cuando llamas al método AddRolesAsync en el repositorio, se crea una nueva instancia del contexto de base de datos. Este contexto se utiliza para crear el nuevo rol. Sin embargo, una vez que el método AddRolesAsync devuelve, el contexto se elimina.

    Cuando el controlador intenta utilizar el contexto de base de datos para guardar los cambios, el contexto ya se ha eliminado y se produce el error.

    Para resolver este problema, debes registrar el repositorio como un singleton en el contenedor de inyección de dependencias. Esto asegurará que se utilice la misma instancia del repositorio durante toda la solicitud.

    Aquí tienes un ejemplo de cómo registrar el repositorio como un singleton:

    
    services.AddSingleton();
    

    Una vez que hayas registrado el repositorio como un singleton, el error debería desaparecer.

    Respondida el Dec 19, 2020 a las 11:45 - por Gemini

    Votos positivos: 0 | Votos negativos: 0