EF Core 1.1 - How to Add migrations in .net core console

.net-core entity-framework-core

Question

There're two projects in my solution as below:

  • Sample.UI: a dotnet core console project created by "dotnet new".
  • Sample.Infrastruction: a dotnet core library created by "dotnet new -t lib", the BlogDbContext is right there.

When I try to run the dotnet ef --startup-project ..\sample.ui migrations add InitialDB in the Sample.Infrastructure folder, it raised an error:

No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.On Configuring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext

The error stack information:

at Microsoft.EntityFrameworkCore.Internal.DatabaseProviderSelector.SelectServices() at Microsoft.EntityFrameworkCore.Internal.LazyRef1.get_Value()

at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Vis itScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)

at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass16_0.b__0(ServiceProvider provider)

at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)

at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)

at Microsoft.EntityFrameworkCore.Design.Internal.DesignTimeServicesBuilder.Build(DbContext context)

at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)

at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)

at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()

at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

I have tried to add AddDbContext to fix the issue, but didn't work for me. Maybe I'm not using the built-in DI correctly. I have googled a lot, but most solutions are used for asp.net core rather then dotnet console.


For your reference, below is the Sample.Infrastructure source code:

namespace Sample.Infrastructure
{
    public class BlogDbContext : DbContext
    {
        public BlogDbContext(DbContextOptions<BlogDbContext> options)
            : base(options)
        {

        }

        public BlogDbContext()
        {
             //ATT: I also don't understand why ef requires the parameterless constructor
        }

        public DbSet<Blog> Blogs { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Blog>().HasKey(post => post.Identity);
            base.OnModelCreating(builder);
        }
    }
}

Sample.UI source code:

namespace Sample.UI
{
    public class Program
    {
        static public IConfigurationRoot Configuration { get; set; }
        private static IServiceProvider _serviceProvider;

        public static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            Configuration = builder.Build();

            //setup DI
            _serviceProvider = new ServiceCollection()
                .AddDbContext<BlogDbContext>(o=> o.UseSqlite(Configuration["ConnectionString"]))
                .BuildServiceProvider();

            // PostApplicationService app = new PostApplicationService();
            // var ctx = _serviceProvider.GetService(typeof(BlogDbContext)) as BlogDbContext;   
            // app.Inital(ctx);

            Console.ReadLine();
        }
    }
}

Update

I have also tried @Morten's solution, execute the following command in Sample.UI folder. However, I got the exactly same error.

dotnet ef --project "C:\SampleDDD\Sample.Infrastructure" --startup-project "C:\SampleDDD\Sample.UI"  migrations add "InitalDB"
1
1
1/22/2017 1:49:39 PM

Accepted Answer

To avoid most commons mistakes when doing EF Core migration, do the following

  1. explicitly write the project parameters in command
    --startup-project < StartProject >, Sample.UI in your case
    --project < ContextProject >, this is the project where your DBContext leaves, Sample.Infrastructure in your case

  2. migrations work with public default constructor or IDbContextFactory if default is absent.So if using default constructor you'll have to override OnConfiguring in your context class, something like

public class BlogDbContext: DbContext 
{
   public DbSet<Blog> Blogs { get; set; }
   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
     string connStr = ConfigurationManager.ConnectionStrings["YourConnName"].ConnectionString;
     optionsBuilder.UseSqlite(connStr);
   }
}

alternativly you can implement IDbContextFactory in the same project where your BlogDbContext resides

public class YourFactory : IDbContextFactory<BlogDbContext>
{
    public BlogDbContextCreate()
    {
        var optionsBuilder = new DbContextOptionsBuilder<BlogDbContext>();
        string connStr = ConfigurationManager.ConnectionStrings["YourConnName"].ConnectionString;
        optionsBuilder.UseSqlite(connStr);

        return new BlogDbContext(optionsBuilder.Options);
    }
}
4
6/8/2017 4:34:47 PM

Popular Answer

You need to add Sample.Infrascruture as --project. Like this:

dotnet ef --project "C:\MYPATH\Sample.Infrastructure" --startup-project "C:\MYPATH\Sample.UI" migrations add "TXT"

And then run it from the Sample.UI project

The same when you do a database upgrade

Also, try to set the connectionstring in BlogDbContext

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 {
     optionsBuilder.UseSqlServer("Server=.;Database=MYDB;Integrated Security=True");
 }


Related Questions





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