无法创建实体框架代码优先迁移



过去几周我一直在开发.NET Core 6控制台应用程序(而不是ASP.NET(,现在我已经尝试实现Entity Framework 6迁移到它。

然而,尽管我重用了使用迁移的工作数据库模型中的一些代码,但现在我无法使其工作,而且由于dotnet-ef的输出不足,我也一直在苦苦挣扎。

由于我记不清的原因,我重用的数据库项目使用了设计时DbContext创建中的代码。我不知道这是否是我进行迁移的最佳方式,但至少它在以前的项目中起到了作用。我以与以前相同的方式实现了所需的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:pabloDocumentssourceMyBotbinDebugnet6.0MyBot.deps.json --additionalprobingpath C:Userspablo.nugetpackages --runtimeconfig F:pabloDocumentssourceMyBotbinDebugnet6.0MyBot.runtimeconfig.json C:Userspablo.dotnettools.storedotnet-ef6.0.1dotnet-ef6.0.1toolsnetcoreapp3.1anytoolsnetcoreapp2.0anyef.dll migrations add Init -o MigrationsInit --assembly F:pabloDocumentssourceMyBotbinDebugnet6.0MyBot.dll --project F:pabloDocumentssourceMyBotMyBot.csproj --startup-assembly F:pabloDocumentssourceMyBotbinDebugnet6.0MyBot.dll --startup-project F:pabloDocumentssourceMyBotMyBot.csproj --project-dir F:pabloDocumentssourceMyBot --root-namespace MyBot--language C# --framework net6.0 --nullable --working-dir F:pabloDocumentssourceMyBot--verbose
Using assembly 'MyBot'.
Using startup assembly 'MyBot'.
Using application base 'F:pabloDocumentssourceMyBotbinDebugnet6.0'.
Using working directory 'F:pabloDocumentssourceMyBot'.
Using root namespace 'MyBot'.
Using project directory 'F:pabloDocumentssourceMyBot'.
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类中:

public MySqlContext(DbContextOptions<MySqlContext> options)
: base(options)
{
}

然后是来自工厂的CCD_ 9。

最新更新