我已经用制作了一个OData服务器.NET core 3.1
。
在此应用程序中,我有2个数据库上下文。其中一项用于应用程序本身(AppDbContext),另一项用于帐户管理和身份验证(AccountDbContext)。
我有一个ServiceExtensions
这样的:
public static class ServiceExtensions
{
public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContext<AppDbContext>(options =>
{
options.UseMySql(configuration.GetConnectionString("MysqlConnection"),
mysqlOptions => {
mysqlOptions.ServerVersion(new ServerVersion(new Version(5, 4, 3), ServerType.MySql));
});
});
services.AddDbContext<AccountDbContext>(options =>
{
options.UseMySql(configuration.GetConnectionString("MysqlConnection"),
mysqlOptions => {
mysqlOptions.ServerVersion(new ServerVersion(new Version(5, 4, 3), ServerType.MySql));
});
});
}
}
在中,startup.cs
我将调用以下ConfigureMySqlContext
函数:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime.
// I use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureMySqlContext(Configuration);
}
}
public static class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
.Build()
.CreateDbIfNotExists()
.Run();
}
private static IHost CreateDbIfNotExists(this IHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var accountDbContext = services.GetRequiredService<AccountDbContext>();
accountDbContext.Database.EnsureCreated();
var appDbContext = services.GetRequiredService<AppDbContext>();
appDbContext.Database.EnsureCreated();
}
return host;
}
}
该代码的目的是在数据库内部的两个上下文中生成所需的表。问题是,当我将该应用程序发布到服务器时,以及当该应用程序首次运行时,它只会生成并初始化中的表AppDbContext
。为什么?因为它放在前面AccountDbContext
。
如果我ConfigureMySqlContext
按照以下方式更改功能并再次发布该应用程序:
public static class ServiceExtensions
{
public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContext<AccountDbContext>(options =>
{
options.UseMySql(configuration.GetConnectionString("MysqlConnection"),
mysqlOptions => {
mysqlOptions.ServerVersion(new ServerVersion(new Version(5, 4, 3), ServerType.MySql));
});
});
services.AddDbContext<AppDbContext>(options =>
{
options.UseMySql(configuration.GetConnectionString("MysqlConnection"),
mysqlOptions => {
mysqlOptions.ServerVersion(new ServerVersion(new Version(5, 4, 3), ServerType.MySql));
});
});
}
}
然后将是AccountDbContext
第一次运行后将在数据库中启动的表中的表。
问题在于,它的核心EnsureCreated
是非常简单的语义,可以将其建模为:
if (!database.exists()) {
database.create();
}
在这里exists()
检查数据库的存在,而不检查数据库中的表是否存在。
最终结果是,如果数据库不是完全为空,EnsureCreated()
则将无效。
有两种方法可以解决此问题:
但是,如果不是这样,请查看:
IRelationalDatabaseCreator.CreateTables()
方法:这是一个可能的解决方案:
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Infrastructure;
public static class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
.Build()
.CreateDbIfNotExists()
.Run();
}
private static IHost CreateDbIfNotExists(this IHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var accountDbContext = services.GetRequiredService<AccountDbContext>();
accountDbContext.Database.EnsureCreated();
var accountDbCreator = accountDbContext.GetService<IRelationalDatabaseCreator>();
accountDbCreator.CreateTables();
}
catch (Exception e) { }
try
{
var appDbContext = services.GetRequiredService<AppDbContext>();
appDbContext.Database.EnsureCreated();
var appDbCreator = appDbContext.GetService<IRelationalDatabaseCreator>();
appDbCreator.CreateTables();
}
catch (Exception e) { }
}
return host;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句