【问题标题】:How to get appsettings from project root to IDesignTimeDbContextFactory implementation in ASP.NET Core 2.0 and EF Core 2.0如何在 ASP.NET Core 2.0 和 EF Core 2.0 中从项目根目录获取应用程序设置到 IDesignTimeDbContextFactory 实现
【发布时间】:2018-04-13 17:22:09
【问题描述】:

我正在使用 ASP.NET Core 2.0 构建应用程序,但遇到 EntityFramework 迁移问题。

我的 DbContext 在一个单独的项目中 (SolutionName\ProjectNamePrefix.Data),因此我为 IDesignTimeDbContextFactory 接口创建了一个实现。

我想为不同的环境使用不同的连接字符串,为此我需要appsettings.json

所以经过快速搜索后,我发现我可以在CreateDbContext 函数中创建一个新的IConfigurationRoot 对象,如下所示: https://codingblast.com/entityframework-core-idesigntimedbcontextfactory/

我添加了它,然后为了测试,尝试从数据项目根文件夹运行dotnet ef migrations list -c MyContext

然后我得到以下错误:

The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\dev\*SolutionName*\*ProjectNamePrefix*.Data\bin\Debug\netcoreapp2.0\appsettings.json'.

所以,基本上,我尝试了 3 个选项来获取正确的根路径:

它们都返回了相同的..\bin\debug\netcoreapp2.0\ 路径。当我从 VS 运行 Data 项目时,前两个选项为我提供了正确的项目根文件夹。

有没有办法获取正确的项目内容根文件夹?

因为当我将 --verbose 添加到 EF 命令时,它会注销一行:

Using content root 'C:\dev\FitsMeIdentity\FitsMeIdentity.Data\'.

所以我知道 EF 不知何故知道项目根目录,但上面提到的所有选项都会返回已构建应用程序的路径。

我发现唯一可行的选择是将Copy output to root folder 更改为Copy always,但从这里发现:https://www.benday.com/2017/02/17/ef-core-migrations-without-hard-coding-a-connection-string-using-idbcontextfactory/ 这不是一个好主意。

起初我什至考虑为 IDesignTimeDbContextFactory 实现创建一个构造函数,该实现将 IOptions 作为参数但不起作用,遇到了与此处解释的相同的问题: Injecting Env Conn String into .NET Core 2.0 w/EF Core DbContext in different class lib than Startup prj & implementing IDesignTimeDbContextFactory

【问题讨论】:

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


    【解决方案1】:

    有点晚了,但这里是那些讨厌硬编码连接字符串的人的解决方案:

    internal class MigrationDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
    {
        public AppDbContext CreateDbContext(string[] args)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", false)
                .Build();
            
            string connectionString = configuration.GetConnectionString("DefaultConnection");
    
            DbContextOptionsBuilder<AppDbContext> optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
            optionsBuilder.UseMySql(connectionString,
                ServerVersion.AutoDetect(connectionString),
                mySqlOptions =>
                    mySqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 10,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null));
    
            return new AppDbContext(optionsBuilder.Options);
        }
    }
    

    【讨论】:

    • 考虑添加 AddEnvironmentVariables 和 AddCommandLine,使配置更像通用主机。
    • 他正在寻找解析 appsettings.json。我不确定 AddEnvironmentVariables 和 AddCommandLine 将如何提供帮助。
    【解决方案2】:

    没有。你不能这样做,更重要的是:你不应该这样做IDesignTimeDbContextFactory 的全部意义在于,它是一种从没有可使用 ASP.NET Core 框架的上下文(即从类库)中获取 DbContext 实例的方法。如果您从 ASP.NET Core 项目运行迁移,则不需要它,如果不需要,则没有可用的配置内容。

    此外,它仅用于开发,因此名称中包含“DesignTime”部分。因此,不需要在不同环境的连接字符串之间切换之类的东西。只需将连接字符串硬编码为docs 详细信息。

    【讨论】:

    • 感谢您的快速回答。好吧,也许我从大局中遗漏了一些东西。将 EF 迁移应用于暂存/生产环境的预期方法是什么?我不应该使用Update-Database,而是应该使用Script-Migration 来获取SQL 脚本并每次手动运行它们?
    • 是的。或者其他创建版本化迁移的方法,例如 ReadyRoll 或类似产品。您也可以创建一个数据库项目。总而言之,有许多不同的方法可以将数据库更改用于生产。只需找到适合您需求的东西。
    • 我很困惑。我认为实体框架是端到端数据库管理的工具。引用thisWhat's the point of this easy to use system if you can't take it all the way? 使用第三方工具进行生产数据库部署对我来说没有意义。或者至少不是付费工具。 ReadyRoll 的网站上明确表示:Please note that ReadyRoll's integration with Entity Framework CodeFirst is evolving and may not be suitable for production use. 我会同时研究 DbUp,但它似乎增加了复杂性。
    • 实体框架只是一个 ORM。它不是也从来没有声称是一个全部、全部、端到端的解决方案,用于您需要对数据库进行的所有操作。生产部署是一个过程。应该有变更管理策略,并且在大多数企业情况下,无论如何,您永远无法在生产数据库的距离内进行 EF 迁移。
    • 您可以通过这种方式在 IDesignTimeDbContextFactory 实现中访问 appsettings.json 配置 - 请参阅我对 Injecting Env Conn String into .NET Core 2.0 w/EF Core DbContext in different class lib than Startup prj & implementing IDesignTimeDbContextFactory 的回答
    猜你喜欢
    • 2018-02-04
    • 2019-01-03
    • 2018-01-21
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多