如何在ASP.NET Core 2.0和EF Core 2.0

时间:2017-11-01 11:44:42

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

我正在ASP.NET Core 2.0中构建一个应用程序,我遇到了EntityFramework Migrations的问题。

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

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

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

我添加了然后进行测试,尝试从Data项目根文件夹运行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项目时,两个第一个选项为我提供了正确的项目根文件夹。

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

因为当我在EF命令中添加了--verbose时,它注销了一行:

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

有点晚了,但对于那些讨厌硬编码连接字符串的人来说,这里有一个解决方案:

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);
    }
}