我正在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个选项来获取正确的根路径:
Directory.GetCurrentDirectory();
env.ContentRootPath;
(IHostingEnvironment
对象,我找到了一种方法来获取它:https://github.com/aspnet/Home/issues/2194)AppDomain.CurrentDomain.BaseDirectory;
并且所有人都返回了相同的..\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
答案 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);
}
}