我想在两个独立的模式中将我的表放在C#ASP.NET Core 2应用程序中。我在appsettings.json
中创建了两个单独的DB上下文和不同的连接字符串。
appsettings.json
"DefaultConnection": "Server=db;Database=DB;User=u;Password=pwd;",
"InventoryCon": "Server=db;Database=DB;User=u;Password=pwd;"
启动:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CustomerDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<InventoryDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("InventoryCon")));
services.AddMvc();
}
我在每个dbContextClasses中指定默认架构: 库存:
...protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("inventory");
}
客户:
...protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("customer");
}
在程序中,我试图将两者都播种:
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<CustomerDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding Customer database.");
}
try
{
var contexti = services.GetRequiredService<InventoryDbContext>();
DbInitializer.InitInventory(contexti);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding Inventory database.");
}
}
host.Run();
}
如果连接字符串是不同的数据库,上面的工作正常,所以我猜它有两个连接字符串到同一个DB的问题。理想情况下,我可以将这些表分离为单独的模式,以便我可以更好地控制查询的访问。
关于如何将表格分成单独的模式的任何想法?
编辑:添加错误:
info:Microsoft.EntityFrameworkCore.Infrastructure [10403] 实体框架Core 2.0.1-rtm-125使用提供程序'Microsoft.EntityFrameworkCore.SqlServer'初始化'InventoryDbContext',其中包含以下选项:无 Microsoft.EntityFrameworkCore.Infrastructure:信息:实体框架核心2.0.1-rtm-125使用提供程序'Microsoft.EntityFrameworkCore.SqlServer'初始化'InventoryDbContext',其中包含以下选项:无 信息:Microsoft.EntityFrameworkCore.Database.Command [20101] 执行DbCommand(32ms)[Parameters = [],CommandType ='Text',CommandTimeout = '30'] IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE ='BASE TABLE')SELECT 1 ELSE SELECT 0 Microsoft.EntityFrameworkCore.Database.Command:Information:Executed DbCommand(32ms)[Parameters = [],CommandType ='Text',CommandTimeout = '30'] IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE ='BASE TABLE')SELECT 1 ELSE SELECT 0 'dotnet.exe''(CoreCLR:clrhost):加载'C:\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App \ 2.0.4 \ System.Diagnostics.StackTrace.dll'。跳过加载符号。模块已优化并启用调试器选项“Just My Code”。 'dotnet.exe''(CoreCLR:clrhost):加载'C:\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App \ 2.0.4 \ System.Reflection.Metadata.dll'。跳过加载符号。模块已优化并启用调试器选项“Just My Code”。 失败:Microsoft.EntityFrameworkCore.Database.Command [20102] 执行DbCommand失败(4ms)[Parameters = [],CommandType ='Text',CommandTimeout = '30'] 选择案例 什么时候存在( 选择1 来自[库存]。[DUA] AS [d]) 然后铸造(1个位)ELSE CAST(0个位) 结束 System.Data.SqlClient.SqlException(0x80131904):无效的对象名称'inventory.DUA'。
在为客户创建架构时,我在日志中注意到以下情况:库存从未发生过: IF SCHEMA_ID(N'customer')IS NULL EXEC(N'CREATE SCHEMA [customer];');
答案 0 :(得分:3)
我想说的是,它抱怨两种语境写入相同的&#39;默认&#39;数据库中的迁移历史表。
要解决此问题,您需要稍微修改一下您的服务配置,以便为每个上下文指定不同的迁移表:
services.AddDbContext<CustomerDbContext>(
options => options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection"),
sqlServerOptions => sqlServerOptions.MigrationsHistoryTable("Customer")));
services.AddDbContext<InventoryDbContext>(
options => options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection"),
sqlServerOptions => sqlServerOptions.MigrationsHistoryTable("Inventory")));
编辑:修复了代码段。
答案 1 :(得分:0)
我的问题是我使用EF和database.EnsureCreated只检查数据库是否存在,如果没有,它会为该上下文创建数据库和指定的模式。在连续调用时,它会看到数据库并且不会创建架构。解释和解决方案是由罗恩米勒here。