使用Entity Framework的迁移命令时,是否可以配置/引导依赖注入?
Entity Framework Core支持DbContext
子类的依赖注入。此机制包括允许在DbContext
之外配置数据访问。
例如,以下内容将使用从config.json
ServiceCollection services = ...
var configuration = new Configuration().AddJsonFile( "config.json" );
services.AddEntityFramework( configuration )
.AddSqlServer()
.AddDbContext<BillingDbContext>( config => config.UseSqlServer() );
但是,迁移命令不知道执行此代码,因此Add-Migration
因缺少提供程序或缺少连接字符串而失败。
通过覆盖OnConfiguring
子类中的DbContext
来指定提供程序和配置字符串,可以使迁移工作,但是当其他地方需要不同的配置时,这会妨碍。最终保持我的迁移命令和我的代码都工作变得非常复杂。
注意:我的DbContext
与使用它的入口点位于不同的程序集中,我的解决方案有多个启动项目。
答案 0 :(得分:4)
正如@bricelam所述,实体框架7中尚不存在此功能.GitHub问题aspnet/EntityFramework#639
跟踪此缺失的功能与此同时,我发现更简单的解决方法是利用全局状态而不是使用子类化。通常不是我的第一个设计选择,但它现在运作良好。
在MyDbContext中:
public static bool isMigration = true;
protected override void OnConfiguring( DbContextOptionsBuilder optionsBuilder )
{
// TODO: This is messy, but needed for migrations.
// See https://github.com/aspnet/EntityFramework/issues/639
if ( isMigration )
{
optionsBuilder.UseSqlServer( "<Your Connection String Here>" );
}
}
在Startup.ConfigureServices()
。
public IServiceProvider ConfigureServices( IServiceCollection services )
{
MyContext.isMigration = false;
var configuration = new Configuration().AddJsonFile( "config.json" );
services.AddEntityFramework( configuration )
.AddSqlServer()
.AddDbContext<MyDbContext>( config => config.UseSqlServer() );
// ...
}
(在我的情况下,配置代码实际上存在于Autofac模块中。)
答案 1 :(得分:2)
如果在与派生DbContext
相同的项目中或在应用程序的启动项目中找到实现此接口的类,则这些工具会绕过创建DbContext
的其他方法,改为使用设计时工厂。
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace MyProject
{
public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
public BloggingContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlite("Data Source=blog.db");
return new BloggingContext(optionsBuilder.Options);
}
}
}
在Entity Framework 2.0,2.1中应用
现在使用IDbContextFactory<TContext>
obsolete。
实现此接口以为没有公共默认构造函数的上下文类型启用设计时服务。设计时服务将自动发现与派生上下文在同一程序集中的此接口的实现。
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace MyProject
{
public class BloggingContextFactory : IDbContextFactory<BloggingContext>
{
public BloggingContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlServer("connection_string");
return new BloggingContext(optionsBuilder.Options);
}
}
}
更多信息:https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
如果您对硬编码的连接字符串不满意,请查看this文章。
答案 2 :(得分:1)
结合上面的答案,这对我有用
private readonly bool isMigration = false;
public MyContext()
{
isMigration = true;
}
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (isMigration)
{
optionsBuilder.UseSqlServer("CONNECTION_STRING");
}
}
答案 3 :(得分:1)
在.NET Core中,应使用自2.1版以来的IDesignTimeDbContextFactory
,因为IDbContextFactory
已过时。
public class FooDbContextFactory : IDesignTimeDbContextFactory<FooDbContext>
{
public FooDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<FooDbContext>();
var connectionString = configuration.GetConnectionString("ConnectionStringName");
builder.UseSqlServer(connectionString);
return new FooDbContext(builder.Options);
}
}
答案 4 :(得分:0)
我知道这是一个老问题,但我使用了onConfiguring方法而且我没有遇到这个问题
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(Startup.Configuration.Get("Data:DefaultConnection:ConnectionString"));
}
答案 5 :(得分:0)
我只是要求一个实例并在我的Startup.cs文件中运行迁移
public void ConfigureServices(IServiceCollection services)
{
// ASPNet Core Identity
services.AddDbContext<RRIdentityDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("RRIdentityConnectionString")));
}
然后在配置中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var rrIdentityContext = app.ApplicationServices.GetService<RRIdentityDbContext>();
rrIdentityContext.Database.Migrate();
}
注意:没有&#39; EnsureCreated&#39;对于数据库。迁移应该创建它,如果它不存在,虽然它应该如何计算出我不知道的权限 - 所以我创建了一个空的数据库。
答案 6 :(得分:0)
如果您正在寻找为imgrations配置共文本的解决方案,则可以在DBContext
类中使用它:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("DbCoreConnectionString");
optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=aspnetcore;Integrated Security=True");
}
}
请记住要安装这两个软件包以具有SetBasePath
和AddJsonFile
方法:
Microsoft.Extensions.Configuration.FileExtensions
Microsoft.Extensions.Configuration.Json