【问题标题】:Override "dbo" schema name in EntityFramework Code First Migrations在 EntityFramework Code First 迁移中覆盖“dbo”模式名称
【发布时间】:2017-12-02 07:03:43
【问题描述】:

我正在尝试使用 EntityFramework Codefirst 和 Oracle 数据库创建一个独立于模式的模型,但 EF 将迁移 dbo 用作模式的默认值。 我在我的 DBContext 上覆盖了 OnModelCreating 方法来解决这个问题,并在 connectionString 中使用用户来代替

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   base.OnModelCreating(modelBuilder);
   modelBuilder.HasDefaultSchema(string.Empty);
}

问题是 __MigrationHistory 忽略了这个默认架构,并且在运行第一次迁移时出现此错误:

ORA-01918: 用户 'dbo' 不存在

尝试this msdn entry 自定义此表的架构。

CustomHistoryContext:

public class CustomHistoryContext : HistoryContext
{
    public CustomHistoryContext(DbConnection dbConnection, string defaultSchema)
            : base(dbConnection, defaultSchema) {}

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.HasDefaultSchema(String.Empty);
    }
}

和 DBConfiguration:

public sealed class Configuration :
        DbMigrationsConfiguration<Model.MyDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
                                 (connection, defaultSchema) => new CustomHistoryContext(connection, defaultSchema));
    }

    protected override void Seed(Model.Model1 context)
    {
    }
}

并且在第一次迁移时工作正常。但是当我修改我的实体模型并尝试使用add-migration 命令反映此更改时,我收到以下错误:

无法生成显式迁移,因为以下原因 显式迁移待定:[201706281804589_initial, 201706281810218_pp2]。在之前应用挂起的显式迁移 尝试生成新的显式迁移。

看起来 EF 丢失了,此时无法找到迁移历史记录。

当我在 Configuration 中评论 SetHistoryContextFactory 指令时,它适用于后续的 add-migration 命令,但是当我想从头开始运行所有迁移(例如部署)时,这种解决方法还不够。

有谁知道我是否可以很好地完成此任务,或者是否有更好的解决方法?

【问题讨论】:

  • 您使用的是哪个 Oracle 提供商?可能是 Oracle 提供程序没有实现此功能的问题。如果您可以快速访问它,也许可以使用 SQL Server 快速尝试一下,看看结果是否相同?此外,不确定是否提供 string.Empty 架构使其默认为嵌入式默认值 (dbo)。
  • 嗨@MichaelWeinand,感谢您的快速评论。我正在使用 Nuget 包中的 Oracle.ManagedDataAccess.EntityFramework v12.1.2400。尝试使用 SQL Server,但 string.Empty 用于 MyDBcontext 架构名称和 sql 脚本是可以的,但对于 CustomHistoryContext 生成的 sql 插入历史中的第一个迁移是:INSERT [CodeFirstDatabase].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])... 注意 CodeFirstDatabase 架构名称
  • 不幸的是,SQL Server 和 Oracle 在架构是什么以及如何与之交互方面的概念略有不同。我猜 [CodeFirstDatabase] 名称是一个内置的默认值,如果你传入 string.Empty 就会使用它。您实际上想将其设置为什么?即使在 Oracle 中,我也不确定您是否真的不能提供模式名称?
  • 一个简化的教程可以在这里找到:oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/…
  • @oskr 嘿,我也有同样的问题。以下答案是否为您解决了问题,或者您是否找到了其他解决方案 - 干杯

标签: c# oracle entity-framework-6 entity-framework-migrations


【解决方案1】:

转到 Migrations -> Configuration.cs 和下面提到的代码。这个修复对我有用!

class Configuration : DbMigrationsConfiguration<CodeFirstOracleProject.Context>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
        SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
                                 (dbc, schema) => historyContextFactory.Invoke(dbc, "YourSchemaName"));
    }
}

【讨论】:

    【解决方案2】:

    再次尝试运行Enable-Migrations -force。然后运行 ​​Add-Migration SomeDescription –IgnoreChanges。之后,运行“Update-Database - Verbose”。这对我有用

    【讨论】:

      【解决方案3】:

      我在 Oracle 的 Configuration : DbMigrationsConfiguration 类中成功尝试了以下操作,以便将历史模式更改为“测试”:

      var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
      SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
                               (dbc, schema) => historyContextFactory.Invoke(dbc, "Test"));
      

      所以基本上,我没有尝试使用未更改的默认架构注册自定义历史上下文,而是尝试使用更改的默认架构注册默认历史上下文。

      结果:当我运行Update-Database -Script 时,生成的脚本包含用于创建__MigrationHistory 表以及插入新历史值的新模式:

      create table "Test"."__MigrationHistory"
          -- ...
      
      insert into "Test"."__MigrationHistory"("MigrationId", "ContextKey", "Model", "ProductVersion") ...
      

      但是,让我们非常清楚:我只是尝试了我期望通过直觉工作的东西,它确实对我有用。我没有找到任何可靠的文档来支持此解决方案。

      【讨论】:

        【解决方案4】:

        打开 Migrations -> Configuration.cs 并添加

         public Configuration()
            {
                AutomaticMigrationsEnabled = false;            
                var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
                SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
                                         (dbc, schema) => historyContextFactory.Invoke(dbc, "your_schema_name_hear"));
        
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-24
          相关资源
          最近更新 更多