.NET Core 2与EF Core不同的上下文在同一个数据库中使用不同的模式(SQL Server)

时间:2018-02-13 04:18:48

标签: c# entity-framework asp.net-core ef-core-2.0

我想在两个独立的模式中将我的表放在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];');

2 个答案:

答案 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