¿Por qué EF7 dice que no he configurado ningún proveedor, cuando ASP.net Identity funciona bien con el mismo DbContext?

asp.net-core c# ef-code-first entity-framework-core

Pregunta

Acabo de comenzar a trabajar en un proyecto experimental con ASP.net 5, MVC6 y Entity Framework 7. Tengo una identidad ASP.Net funcionando bien, pero luego intenté agregar algunos de mis propios datos a DbContext y resolví este problema. Informes EF7:

Se produjo una excepción no controlada al procesar la solicitud.

InvalidOperationException: no hay proveedores de bases de datos configurados. Configure un proveedor de base de datos anulando OnConfiguring en su clase DbContext o en el método AddDbContext al configurar los servicios.

Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices (ServiceProviderSource providerSource) Encabezados de cookies de consulta de pila

InvalidOperationException: no hay proveedores de bases de datos configurados. Configure un proveedor de base de datos anulando OnConfiguring en su clase DbContext o en el método AddDbContext al configurar los servicios.

Aquí está mi método de configuración:

    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Add application services.
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();

        services.AddTransient<ApplicationUnitOfWork>(instance => new ApplicationUnitOfWork());
    }

ApplicationUnitOfWork es una fachada sobre EF7 para reducir el acoplamiento apretado. Aquí está todo el asunto hasta ahora:

public class ApplicationUnitOfWork : IUnitOfWork
    {
    readonly ApplicationDbContext dbContext;

    public ApplicationUnitOfWork()
        {
        dbContext = new ApplicationDbContext();
        Products = new ProductRepository(dbContext);
        }

    public void Dispose() { dbContext.Dispose(); }

    public IUserRepository Users { get; }

    public IRepository<SoftwareProduct> Products { get; }

    public async Task CommitAsync() { await dbContext.SaveChangesAsync(); }

    public void Cancel() { throw new NotImplementedException(); }
    }

Ahora, cuando ejecuto la aplicación web, puedo registrar una cuenta de usuario e iniciar sesión y EF crea la base de datos, crea las tablas de identidad y las llena con los datos del usuario. La tabla de productos también se crea, por lo que claramente en algún nivel, EF puede usar ApplicationDbContext y encontrar un proveedor que utiliza para crear la base de datos y el esquema.

Sin embargo, cuando trato de acceder a mi controlador de Productos, que usa el Repositorio de ProductsRepository , EF se queja, ¡aunque ApplicationDbContext se usa en ambos casos y se usó para crear la base de datos!

Entonces, ¿cómo es que? ¿Qué tiene de especial la identidad de ASP.net que puede obtener un proveedor, pero mi propio código no puede? ¿Qué "conjuro mágico" me estoy perdiendo?

Respuesta aceptada

Es porque lo estás renovando en lugar de que te lo inyecten. El que estás actualizando no ha sido configurado. Debes cambiar tu clase para que pase al constructor.

DbContext tiene más de un constructor y está usando el vacío que no lo configura.

Es mejor dejar que se inyecte haciendo que tu constructor sea así:

 public ApplicationUnitOfWork(ApplicationDbContext context)
 {
    dbContext = context;
    Products = new ProductRepository(dbContext);
 }

su código muestra que ApplicationDbContext se ha registrado con el DI, Identity está usando el inyectado, pero usted no lo hizo, ya que lo actualizó usted mismo con el constructor sin parámetros

También debe registrar su ApplicationUnitOfWork para que pueda ser inyectado:

services.AddScoped<ApplicationUnitOfWork, ApplicationUnitOfWork>();


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow