Entity Framework 7 no database provider is configured => when migrations are moved to another project

asp.net-core c# entity-framework-core

Question

I am new to EF7. I know this is a duplicate question to:

No database providers are configured EF7

But wait before you want to have this question closed... and read on

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

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

  services.AddScoped<TestRepository, TestRepository>();

Now I run the dnx ef database update command on the cmd windows in my EF project and get this error:

C:\TGB.DataAccess>dnx ef database update
System.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.
   bei Microsoft.Data.Entity.Internal.DatabaseProviderSelector.SelectServices(ServiceProviderSource providerSource)
   bei Microsoft.Data.Entity.Internal.DbContextServices.<>c__DisplayClass6_0.<Initialize>b__0()
   bei Microsoft.Data.Entity.Internal.LazyRef`1.get_Value()
   bei Microsoft.Data.Entity.Internal.DbContextServices.get_DatabaseProviderServices()
   bei Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c.<AddEntityFramework>b__0_8(IServiceProvider p)
   bei Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryService.Invoke(ServiceProvider provider)
   bei Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
   bei Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass12_0.<RealizeService>b__0(ServiceProvider provider)
   bei Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   bei Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   bei Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService[T](IServiceProvider provider)
   bei Microsoft.Data.Entity.Design.Internal.DesignTimeServicesBuilder.Build(DbContext context)
   bei Microsoft.Data.Entity.Design.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
   bei Microsoft.Data.Entity.Commands.Program.Executor.<>c__DisplayClass7_0.<UpdateDatabase>b__0()
   bei Microsoft.Data.Entity.Commands.Program.Executor.Execute(Action action)
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.

Now I tried to change the constructor of my ApplicationDbContext according to the solution link I pasted at the top:

Thats my code:

My ApplicationDbContext.cs is actually empty that means nothing I have overridden.

Looking at the base class of the base class there is the overloaded constructor with parameter DbContextOptions but I can not pass anything from my constructor?!

  //
        // Summary:
        //     Initializes a new instance of Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext.
        //
        // Parameters:
        //   options:
        //     The options to be used by a Microsoft.Data.Entity.DbContext.
        public IdentityDbContext(DbContextOptions options);

What is broken on my side? I am using EF 7 RC1 and dnx 451.

This happens only when you move the ApplicationDbContext/ApplicationUser and the whole Migrations folder to an extra lets say "DataAccess" project. Then everything seems broken.

Accepted Answer

  1. Create a new ASP.NET Web Application named "WebProject" using Web Application template (Authentication: Individual User Account).

  2. Now add another project to the solution named "DataAccess" (let's say Class Library type though its not relevant)

  3. Now move ApplicationDbContext/ApplicationUser files & migrations folder to DataAccess project.

  4. At this stage the build will be failing, so we need to correct the project.json for correct references.

  5. For DataAccess project, add following dependencies

    "dependencies": {
        "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
        "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final"
    }
    
  6. For WebProject, add DataAccess as dependency. Since DataAccess has reference to above 2 packages, you can remove those references from WebProject.
    Build should succeed now and you can launch web application.

How to use ef migrations:

In command line, go to directory of WebProject (and not the DataAccess project). All the ef commands will work fine from here.

To add new migrations to the Migrations folder of DataAccess project, you need to use -p flag. Like,
dnx ef migrations add Sample -p DataAccess.

The issue arises because the commands are run from cmd within DataAccess project. Your startup class which is initializing all the services is in WebProject. When you try to run commands from DataAccess directory, dnx ef will be recognized since EntityFramework.Commands is referenced but when you try to use the migrations, services are not initialized therefore it will fail throwing above exception.


Popular Answer

Try to move your Context class to your "DataAccess" project and override the OnConfiguring method of your Context in your "DataAccess" project then run the migration.

public partial class MyContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlServer(@"Server=****;Database=***;user id=***;password=***");
    }
}

Or you can do like followings if you don't want to hard code your connection string. DI will inject the options for you;

public partial class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options)
    {

    }
}

and on your Startup.cs;

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json")
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddEntityFramework()
        .AddSqlServer()            
        .AddDbContext<WtContext>(options =>
            options.UseSqlServer(Configuration["Data:MyDb:ConnectionString"]));
}

and your appsetting.json;

{
  "Data": {
    "MyDb": {
      "ConnectionString": "**********"
    }
  }
}



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why