This bit me hard, getting errors like:
No database provider has been configured for this DbContext.
No design-time services were found.
The server was not found or was not accessible.
But I ended up with a fairly simple solution/work-around:
- Set the default startup-project in your solution (or in your command line)
in your Startup.cs
add the migration-project:
public void ConfigureServices(IServiceCollection services)
{
var myDbContextAssemblyName = typeof(MyDbContext).Assembly.GetName().Name;
var connectionString = Configuration.GetConnectionString(MyDbContext.ConnectionStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
connectionString,
x => x.MigrationsAssembly(myDbContextAssemblyName)));
// do more ...
}
in your connection-string use the IP-address and port-number (inspired by this corefx issue), instead of the server-name/dns (FWIW: query to get IP).
So now I have this in my appsettings.Development.json
:
"ConnectionStrings": {
"MyConnectionStringName": "Data Source=10.1.2.3,1433; Initial Catalog=MyCatalog; Integrated Security=SSPI"
}
TLDR: other suggestions
I found a lot of other suggestions, and I will mention a few that seemed interesting. Maybe it will help someone else:
Project-names in command-line
Mention startup-project and migration-project in command-line:
Update-Database -Verbose -Project x.Data -StartupProject x.Web
Migrate from code
One can also call migrations at StartUp
, "for apps with a local database". (I guess otherwise running on multiple nodes, may start multiple runtime migrations at the same time with concurrency issues?)
myDbContext.Database.Migrate();
Set DbContext in Main.cs
This EntityFrameworkCore issue states:
The problem is that when EF calls either CreateWebHostBuilder
or
BuildWebHost
it does so without running Main
. (This is intentional
because EF needs to build the model and use the DbContext
without
starting the application.) This means that when EF invokes on of these
methods the static IConfiguration
property is still null--since it
is only set in Main
. So, you'll need to either make sure that
IConfiguration
is set/handled when EF calls one of these methods, or
use IDesignTimeDbContextFactory
.
This is not necessary for me, I guess because .Net Core 2 loads the configuration behind the scenes.
Use IDesignTimeDbContextFactory with environment variable
This EntityFrameworkCore issue states:
The typical way to do this is to read a file, an environment variable, or similar inside IDesignTimeDbContextFactory
.
This seems too much a hack to me.
DbContext-creation at design time
Microsoft documentation mentions:
Some of the EF Core Tools commands (for example, the Migrations
commands) require a derived DbContext instance to be created at design
time in order to gather details about the application's entity types
and how they map to a database schema.
They mention these ways to provide this design time DbContext:
from application services: for an ASP.NET Core app as startup project:
The tools try to obtain the DbContext
object from the application's
service provider. [...] The tools first try to obtain the service
provider by invoking Program.BuildWebHost()
[JP: or
CreateWebHostBuilder
] and accessing the IWebHost.Services
property. The DbContext
itself and any dependencies in its
constructor need to be registered as services in the application's
service provider. This can be easily achieved by having a constructor
on the DbContext
that takes an instance of
DbContextOptions<TContext>
as an argument and using the
AddDbContext<TContext>
method.
Using a constructor with no parameters
If the DbContext
can't be obtained from the application service
provider, the tools look for the derived DbContext
type inside the
project. Then they try to create an instance using a constructor with
no parameters. This can be the default constructor if the DbContext
is configured using the OnConfiguring
method.
From a design-time factory
You can also tell the tools how to create your DbContext
by
implementing the IDesignTimeDbContextFactory<TContext>
interface: If
a class implementing this interface is found in either the same
project as the derived DbContext or in the application's startup
project, the tools bypass the other ways of creating the DbContext
and use the design-time factory.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…