There're two projects in my solution as below:
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"
To avoid most commons mistakes when doing EF Core migration, do the following
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
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);
}
}
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");
}