Perché EF7 dice che non ho configurato alcun provider, quando ASP.net Identity funziona correttamente con lo stesso DbContext?

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

Domanda

Ho appena iniziato a lavorare su un progetto sperimentale usando ASP.net 5, MVC6 ed Entity Framework 7. Ho ASP.Net Identity che funziona bene, ma poi ho provato ad aggiungere alcuni dei miei dati al DbContext e ho riscontrato questo problema. Rapporti EF7:

Si è verificata un'eccezione non gestita durante l'elaborazione della richiesta.

InvalidOperationException: nessun provider di database è configurato. Configurare un provider di database eseguendo l'override di OnConfiguring nella classe DbContext o nel metodo AddDbContext durante l'impostazione dei servizi.

Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices (ServiceProviderSource providerSource) Stack query cookie Intestazioni

InvalidOperationException: nessun provider di database è configurato. Configurare un provider di database eseguendo l'override di OnConfiguring nella classe DbContext o nel metodo AddDbContext durante l'impostazione dei servizi.

Ecco il mio metodo di configurazione:

    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 è una facciata su EF7 per ridurre l'accoppiamento stretto. Ecco il tutto fino ad ora:

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(); }
    }

Ora quando eseguo l'applicazione Web, sono in grado di registrare un account utente e accedere e EF crea il database, crea le tabelle Identity e le popola con i dati dell'utente. Viene creata anche la tabella dei prodotti - in modo chiaro a un certo livello EF è in grado di utilizzare ApplicationDbContext e trovare un provider che utilizza per creare il database e lo schema.

Tuttavia, quando provo ad accedere al mio controller Products, che utilizza il repository ProductsRepository , EF si lamenta, anche se ApplicationDbContext è utilizzato in entrambi i casi ed è stato utilizzato per creare il database!

Allora, come mai? Qual è la particolarità di ASP.net Identity che può in qualche modo ottenere un provider, ma il mio codice non può? Quale "incantesimo magico" mi manca?

Risposta accettata

è perché lo stai facendo di nuovo invece di averlo iniettato per te. Quello che stai facendo il nuovo non è stato configurato. Dovresti cambiare classe per farlo passare nel costruttore.

DbContext ha più di un costruttore e stai utilizzando quello vuoto che non lo configura.

Meglio lasciarlo iniettare rendendo il tuo costruttore così:

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

il tuo codice mostra che ApplicationDbContext è stato registrato con il DI, Identity sta usando l'iniettato ma non lo sei da quando lo hai aggiornato con il costruttore senza parametri

dovresti anche registrare il tuo ApplicationUnitOfWork in modo che possa essere iniettato:

services.AddScoped<ApplicationUnitOfWork, ApplicationUnitOfWork>();


Related

Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow