【发布时间】:2022-01-23 19:45:01
【问题描述】:
过去几周我一直在开发 .NET Core 6 控制台应用程序(不是 ASP.NET),现在我尝试实现 Entity Framework 6 迁移到它。
但是,即使我重用了使用迁移的工作数据库模型中的一些代码,但现在我无法使其工作,并且由于缺少来自 dotnet-ef 的输出,我也一直在苦苦挣扎。
由于我不记得的原因,我重用了来自 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\6.0.1\dotnet-ef\6.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();
}
但不幸的是,我的应用程序计划与数据库动态交互,因此 Code-First 配置方法对我无效。
我该如何解决这个问题?是方法问题,还是我在搞乱自定义的非 ASP.NET 依赖注入提供程序?谢谢大家
【问题讨论】:
-
这看起来像错误:
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.并且可能被欺骗:stackoverflow.com/questions/45782446/…。您可以查看您的 Program.cs 文件吗? -
问题是我的应用程序不是 ASP.NET,因此我没有 Startup 类可以插入到主机生成器中,也没有通常的 ASP.NET 初始化模式。我应该移植我的控制台应用程序以实现这一目标吗?
标签: c# entity-framework .net-core entity-framework-migrations .net-6.0