无法创建 Entity Framework 代码优先迁移
Can't create Entity Framework code-first migrations
过去几周我一直在开发 .NET Core 6 控制台应用程序(不是 ASP.NET),现在我已经尝试实施 Entity Framework 6 次迁移。
然而,即使我重用了使用迁移的工作数据库模型中的一些代码,现在我也无法让它工作,而且由于缺少 [=16= 的输出,我也一直在努力].
由于我不记得的原因,我重用了代码的数据库项目使用了 Design-Time DbContext creation。我不知道这是否是我进行迁移的最佳方式,但至少它设法在以前的项目中工作。我以与之前相同的方式实现了所需的 IDesignTimeDbContextFactory<DbContext>
接口:
public class MySqlContextFactory : IDesignTimeDbContextFactory<MySqlContext>
{
public MySqlContext CreateDbContext(string[] args)
{
DbContextOptionsBuilder optionsBuilder = new();
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(DatabaseCredentials.GetConnectionString(), mariaDbVersion);
return new MySqlContext();
}
}
public class MySqlContext : DbContext
{
public DbSet<Endpoint> EndpointsSet { get; set; }
private readonly string _connectionString;
public MySqlContext() : base()
=> _connectionString = DatabaseCredentials.GetConnectionString();
public MySqlContext(string connectionString) : base()
=> _connectionString = connectionString;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> Configurator.Configure(optionsBuilder, _connectionString);
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> Configurator.Create(modelBuilder);
}
public static void Configure(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(connectionString, mariaDbVersion);
}
public static void Create(ModelBuilder modelBuilder)
{
IEnumerable<Type> types = ReflectionUtils.GetImplementedTypes(typeof(IEntityTypeConfiguration<>));
if (types.Any())
{
foreach (Type entityConfigurationType in types)
{
modelBuilder.ApplyConfigurationsFromAssembly(entityConfigurationType.Assembly);
}
}
else
{
Environment.Exit((int) EExitCodes.EF_MODEL_NOT_FOUND);
}
}
但是,当我尝试创建第一个迁移时,系统提示我从 dotnet-ef 工具输出这个绝对非描述性的输出:
PS> dotnet ef migrations add Init
Build started...
Build succeeded.
PS>
但是我的项目没有进行任何迁移,也没有任何更改。因此,我决定通过在 PS 命令上附加 --verbose
标志来强制 dotnet ef 告诉我更多信息:
[...]
Build succeeded.
dotnet exec --depsfile F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.deps.json --additionalprobingpath C:\Users\pablo\.nuget\packages --runtimeconfig F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.runtimeconfig.json C:\Users\pablo\.dotnet\tools\.store\dotnet-ef.0.1\dotnet-ef.0.1\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll migrations add Init -o Migrations\Init --assembly F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.dll --project F:\pablo\Documents\source\MyBot\MyBot.csproj --startup-assembly F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.dll --startup-project F:\pablo\Documents\source\MyBot\MyBot.csproj --project-dir F:\pablo\Documents\source\MyBot\ --root-namespace MyBot--language C# --framework net6.0 --nullable --working-dir F:\pablo\Documents\source\MyBot--verbose
Using assembly 'MyBot'.
Using startup assembly 'MyBot'.
Using application base 'F:\pablo\Documents\source\MyBot\bin\Debug\net6.0'.
Using working directory 'F:\pablo\Documents\source\MyBot'.
Using root namespace 'MyBot'.
Using project directory 'F:\pablo\Documents\source\MyBot\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Found IDesignTimeDbContextFactory implementation 'MySqlContextFactory'.
Found DbContext 'MySqlContext'.
Finding application service provider in assembly 'MyBot'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Using DbContext factory 'MySqlContextFactory'.
PS>
我认为我可以搜索的第一件事是 CreateHostBuilder
该工具搜索但不检索的功能。然而,再一次,我能找到的所有文档都是参考 ASP.NET 应用程序和我没有在我的机器人应用程序中实现的编程模式。我的应用程序确实通过定制的依赖注入检索服务(也许这就是 No application service provider was found.
行的原因?),但我没有找到一种方法来实现该 CreateHostBuilder 函数而不更改所有内容。
只是为了添加信息,这就是我使用非迁移方法设法创建和配置 EF 模型的方式:
public static IServiceProvider GetServices(DiscordSocketClient client, CommandService commands)
{
ServiceCollection services = new();
services.AddSingleton(client);
services.AddSingleton(commands);
services.AddSingleton<HttpClient>();
services.AddDbContext<MySqlContext>(ServiceLifetime.Scoped);
return AddServices(services) // builds service provider;
}
private static async Task InitDatabaseModel(IServiceProvider provider)
{
MySqlContext? dbCtxt = provider.GetService<MySqlContext>();
if (dbCtxt == null)
{
Environment.Exit((int) EExitCodes.DB_SERVICE_UNAVAILABLE);
}
await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.EnsureCreatedAsync();
}
但不幸的是,我的应用程序计划与数据库动态交互,因此代码优先配置方法对我无效。
我该如何解决这个问题?是方法问题,还是我在搞乱自定义非 ASP.NET 依赖注入提供程序?谢谢大家
您的 IDesignTimeDbContextFactory
有问题。 EF Core 正在尝试为您的这个工厂创建一个 MySqlContext
.
public class MySqlContextFactory : IDesignTimeDbContextFactory<MySqlContext>
{
public MySqlContext CreateDbContext(string[] args)
{
// set up options
DbContextOptionsBuilder optionsBuilder = new();
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(DatabaseCredentials.GetConnectionString(), mariaDbVersion);
// *** this is the issue ***
// return default constructor W/O options (ie, UseMySql is never called)
return new MySqlContext();
}
}
您可以将此构造函数添加到您的 DbContext
class:
public MySqlContext(DbContextOptions<MySqlContext> options)
: base(options)
{
}
然后 return new MySqlContext(optionsBuilder.Options)
来自您的工厂。
过去几周我一直在开发 .NET Core 6 控制台应用程序(不是 ASP.NET),现在我已经尝试实施 Entity Framework 6 次迁移。
然而,即使我重用了使用迁移的工作数据库模型中的一些代码,现在我也无法让它工作,而且由于缺少 [=16= 的输出,我也一直在努力].
由于我不记得的原因,我重用了代码的数据库项目使用了 Design-Time DbContext creation。我不知道这是否是我进行迁移的最佳方式,但至少它设法在以前的项目中工作。我以与之前相同的方式实现了所需的 IDesignTimeDbContextFactory<DbContext>
接口:
public class MySqlContextFactory : IDesignTimeDbContextFactory<MySqlContext>
{
public MySqlContext CreateDbContext(string[] args)
{
DbContextOptionsBuilder optionsBuilder = new();
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(DatabaseCredentials.GetConnectionString(), mariaDbVersion);
return new MySqlContext();
}
}
public class MySqlContext : DbContext
{
public DbSet<Endpoint> EndpointsSet { get; set; }
private readonly string _connectionString;
public MySqlContext() : base()
=> _connectionString = DatabaseCredentials.GetConnectionString();
public MySqlContext(string connectionString) : base()
=> _connectionString = connectionString;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> Configurator.Configure(optionsBuilder, _connectionString);
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> Configurator.Create(modelBuilder);
}
public static void Configure(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(connectionString, mariaDbVersion);
}
public static void Create(ModelBuilder modelBuilder)
{
IEnumerable<Type> types = ReflectionUtils.GetImplementedTypes(typeof(IEntityTypeConfiguration<>));
if (types.Any())
{
foreach (Type entityConfigurationType in types)
{
modelBuilder.ApplyConfigurationsFromAssembly(entityConfigurationType.Assembly);
}
}
else
{
Environment.Exit((int) EExitCodes.EF_MODEL_NOT_FOUND);
}
}
但是,当我尝试创建第一个迁移时,系统提示我从 dotnet-ef 工具输出这个绝对非描述性的输出:
PS> dotnet ef migrations add Init
Build started...
Build succeeded.
PS>
但是我的项目没有进行任何迁移,也没有任何更改。因此,我决定通过在 PS 命令上附加 --verbose
标志来强制 dotnet ef 告诉我更多信息:
[...]
Build succeeded.
dotnet exec --depsfile F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.deps.json --additionalprobingpath C:\Users\pablo\.nuget\packages --runtimeconfig F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.runtimeconfig.json C:\Users\pablo\.dotnet\tools\.store\dotnet-ef.0.1\dotnet-ef.0.1\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll migrations add Init -o Migrations\Init --assembly F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.dll --project F:\pablo\Documents\source\MyBot\MyBot.csproj --startup-assembly F:\pablo\Documents\source\MyBot\bin\Debug\net6.0\MyBot.dll --startup-project F:\pablo\Documents\source\MyBot\MyBot.csproj --project-dir F:\pablo\Documents\source\MyBot\ --root-namespace MyBot--language C# --framework net6.0 --nullable --working-dir F:\pablo\Documents\source\MyBot--verbose
Using assembly 'MyBot'.
Using startup assembly 'MyBot'.
Using application base 'F:\pablo\Documents\source\MyBot\bin\Debug\net6.0'.
Using working directory 'F:\pablo\Documents\source\MyBot'.
Using root namespace 'MyBot'.
Using project directory 'F:\pablo\Documents\source\MyBot\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Found IDesignTimeDbContextFactory implementation 'MySqlContextFactory'.
Found DbContext 'MySqlContext'.
Finding application service provider in assembly 'MyBot'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Using DbContext factory 'MySqlContextFactory'.
PS>
我认为我可以搜索的第一件事是 CreateHostBuilder
该工具搜索但不检索的功能。然而,再一次,我能找到的所有文档都是参考 ASP.NET 应用程序和我没有在我的机器人应用程序中实现的编程模式。我的应用程序确实通过定制的依赖注入检索服务(也许这就是 No application service provider was found.
行的原因?),但我没有找到一种方法来实现该 CreateHostBuilder 函数而不更改所有内容。
只是为了添加信息,这就是我使用非迁移方法设法创建和配置 EF 模型的方式:
public static IServiceProvider GetServices(DiscordSocketClient client, CommandService commands)
{
ServiceCollection services = new();
services.AddSingleton(client);
services.AddSingleton(commands);
services.AddSingleton<HttpClient>();
services.AddDbContext<MySqlContext>(ServiceLifetime.Scoped);
return AddServices(services) // builds service provider;
}
private static async Task InitDatabaseModel(IServiceProvider provider)
{
MySqlContext? dbCtxt = provider.GetService<MySqlContext>();
if (dbCtxt == null)
{
Environment.Exit((int) EExitCodes.DB_SERVICE_UNAVAILABLE);
}
await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.EnsureCreatedAsync();
}
但不幸的是,我的应用程序计划与数据库动态交互,因此代码优先配置方法对我无效。
我该如何解决这个问题?是方法问题,还是我在搞乱自定义非 ASP.NET 依赖注入提供程序?谢谢大家
您的 IDesignTimeDbContextFactory
有问题。 EF Core 正在尝试为您的这个工厂创建一个 MySqlContext
.
public class MySqlContextFactory : IDesignTimeDbContextFactory<MySqlContext>
{
public MySqlContext CreateDbContext(string[] args)
{
// set up options
DbContextOptionsBuilder optionsBuilder = new();
ServerVersion mariaDbVersion = new MariaDbServerVersion(new Version(10, 6, 5));
optionsBuilder.UseMySql(DatabaseCredentials.GetConnectionString(), mariaDbVersion);
// *** this is the issue ***
// return default constructor W/O options (ie, UseMySql is never called)
return new MySqlContext();
}
}
您可以将此构造函数添加到您的 DbContext
class:
public MySqlContext(DbContextOptions<MySqlContext> options)
: base(options)
{
}
然后 return new MySqlContext(optionsBuilder.Options)
来自您的工厂。