Pourquoi EF7 dit-il que je n'ai configuré aucun fournisseur alors qu'ASP.net Identity fonctionne correctement avec le même DbContext?

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

Question

Je viens tout juste de commencer à travailler sur un projet expérimental utilisant ASP.net 5, MVC6 et Entity Framework 7. Je réussis à bien utiliser ASP.Net Identity, mais j'ai ensuite essayé d'ajouter certaines de mes propres données au DbContext et de résoudre ce problème. EF7 rapporte:

Une exception non gérée s'est produite lors du traitement de la demande.

InvalidOperationException: aucun fournisseur de base de données n'est configuré. Configurez un fournisseur de base de données en remplaçant OnConfiguring dans votre classe DbContext ou dans la méthode AddDbContext lors de la configuration des services.

Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices (ServiceProviderSource providerSource) En-têtes des cookies de la requête de pile

InvalidOperationException: aucun fournisseur de base de données n'est configuré. Configurez un fournisseur de base de données en remplaçant OnConfiguring dans votre classe DbContext ou dans la méthode AddDbContext lors de la configuration des services.

Voici ma méthode de configuration:

    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 est une façade par rapport à EF7 pour réduire le couplage étroit. Voici le tout jusqu'à présent:

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

Maintenant, lorsque je lance l'application Web, je peux créer un compte utilisateur et me connecter. EF crée la base de données, crée les tables d'identité et les remplit avec les données de l'utilisateur. La table products est également créée. Ainsi, à un certain niveau, EF est capable d’utiliser ApplicationDbContext et de trouver un fournisseur qu’il utilise pour créer la base de données et le schéma.

Cependant, lorsque j'essaie d'accéder à mon contrôleur Products, qui utilise ProductsRepository , EF se plaint, même si ApplicationDbContext est utilisé dans les deux cas et a été utilisé pour créer la base de données!

Alors comment venir? En quoi ASP.net Identity a-t-il la particularité de pouvoir obtenir un fournisseur, mais que mon propre code ne le puisse pas? Quelle "incantation magique" me manque?

Réponse acceptée

c’est parce que vous le renouvelez au lieu de l’avoir injecté pour vous. Celui que vous venez de créer n’a pas été configuré. Vous devriez changer votre classe pour le faire passer au constructeur.

DbContext a plusieurs constructeurs et vous utilisez le constructeur vide qui ne le configure pas.

Mieux vaut le laisser s'injecter en faisant votre constructeur comme ceci:

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

votre code montre qu'ApplicationDbContext a été enregistré auprès de la DI, Identity utilise l'injecté mais vous ne l'êtes plus depuis que vous l'avez créé vous-même avec le constructeur sans paramètre.

vous devez également enregistrer votre ApplicationUnitOfWork pour pouvoir l’injecter:

services.AddScoped<ApplicationUnitOfWork, ApplicationUnitOfWork>();


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow