Why does EF7 say I haven't configured any providers, when ASP.net Identity is working fine with the same DbContext?

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

Question

I've just started work on an experimental project using ASP.net 5, MVC6 and Entity Framework 7. I have ASP.Net Identity working fine, but then tried to add some of my own data to the DbContext and hit this problem. EF7 reports:

An unhandled exception occurred while processing the request.

InvalidOperationException: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.

Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices(ServiceProviderSource providerSource) Stack Query Cookies Headers

InvalidOperationException: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.

Here's my configuration method:

    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 is a façade over EF7 to reduce tight coupling. Here's the whole thing so far:

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

Now when I run the web application, I am able to register a user account and log in and EF creates the database, creates the Identity tables and populates them with user data. The products table is also created - so clearly at some level EF is able to use the ApplicationDbContext and find a provider which it uses to create the database and schema.

However when I try to access my Products controller, which uses the ProductsRepository, EF complains - even though ApplicationDbContext is used in both cases and was used to create the database!

So how come? What's special about ASP.net Identity that it can somehow obtain a provider, but my own code can't? What "magic incantation" am I missing?

Accepted Answer

its because you are newing it up instead of having it injected for you. The one you are newing up hasn't been configured. You should change your class to have it passed into the constructor.

DbContext has more than one constructor and you are using the empty one which doesn't configure it.

Better to let it be injected by making your constructor like this:

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

your code shows that ApplicationDbContext has been registered with the DI, Identity is using the injected one but you are not since you newed it up yourself with the parameterless constructor

you should also register your ApplicationUnitOfWork so it can be injected:

services.AddScoped<ApplicationUnitOfWork, ApplicationUnitOfWork>();


Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow