我有一个.Net Core WebApplication项目,其中Context类位于类库中。如果我在OnConfiguring(DbContextOptionsBuilder optionsBuilder)方法中对连接字符串进行硬编码,我可以生成迁移。由于最好让依赖注入管理上下文,我想将它添加到Startup Class。但是当我这样做时,我收到以下错误:
没有为此DbContext配置数据库提供程序。可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。如果使用AddDbContext,那么还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基础构造函数。
DbContext类:
public class CustomerManagerContext : IdentityDbContext<User, Role, long, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
{
public CustomerManagerContext() { }
public CustomerManagerContext(DbContextOptions<CustomerManagerContext> options) : base(options)
{
}
//protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
//{
// base.OnConfiguring(optionsBuilder);
// optionsBuilder.UseSqlServer("SecretConnectionString");
//}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>().ToTable("Users");
builder.Entity<Role>().ToTable("Roles");
builder.Entity<UserClaim>().ToTable("UserClaims");
builder.Entity<UserRole>().ToTable("UserRoles");
builder.Entity<UserLogin>().ToTable("UserLogins");
builder.Entity<RoleClaim>().ToTable("RoleClaims");
builder.Entity<UserToken>().ToTable("UserTokens");
}
}
启动类 - ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CustomerManagerContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
);
services.AddEntityFrameworkSqlServer()
.AddDbContext<CustomerManagerContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<CustomerManagerContext>()
.AddDefaultTokenProviders();
}
这让我很难,得到的错误如下:
No database provider has been configured for this DbContext.
No design-time services were found.
The server was not found or was not accessible.
但我最终得到了一个相当简单的解决方案/解决方案:
Startup.cs
add the migration-project:
public void ConfigureServices(IServiceCollection services)
{
var myDbContextAssemblyName = typeof(MyDbContext).Assembly.GetName().Name;
var connectionString = Configuration.GetConnectionString(MyDbContext.ConnectionStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
connectionString,
x => x.MigrationsAssembly(myDbContextAssemblyName)));
// do more ...
}
appsettings.Development.json
中有这个:
“ConnectionStrings”:{“MyConnectionStringName”:“Data Source = 10.1.2.3,1433; Initial Catalog = MyCatalog; Integrated Security = SSPI”}我发现了很多其他建议,我会提到一些看似有趣的建议。也许它会帮助别人:
在命令行中提到启动项目和迁移项目:
Update-Database -Verbose -Project x.Data -StartupProject x.Web
也可以在StartUp上调用迁移,“对于具有本地数据库的应用程序”。 (我想否则在多个节点上运行,可能会在并发问题的同时启动多个运行时迁移?)
myDbContext.Database.Migrate();
This EntityFrameworkCore issue说:
问题是,当EF调用
CreateWebHostBuilder
或BuildWebHost
时,它会在不运行Main
的情况下执行此操作。 (这是故意的,因为EF需要构建模型并在不启动应用程序的情况下使用DbContext
。)这意味着当EF调用这些方法时,静态IConfiguration
属性仍为null - 因为它仅在Main
中设置。因此,当EF调用其中一种方法时,您需要确保设置/处理IConfiguration
,或者使用IDesignTimeDbContextFactory
。
这对我来说不是必需的,我猜是因为.Net Core 2 loads the configuration behind the scenes。
This EntityFrameworkCore issue说:
执行此操作的典型方法是在
IDesignTimeDbContextFactory
中读取文件,环境变量或类似内容。
这对我来说似乎太过分了。
某些EF Core Tools命令(例如,迁移命令)需要在设计时创建派生的DbContext实例,以便收集有关应用程序的实体类型以及它们如何映射到数据库模式的详细信息。
他们提到了这些设计时间DbContext的方法:
DbContext
对象。 [...]工具首先尝试通过调用Program.BuildWebHost()
[JP:或CreateWebHostBuilder
]并访问IWebHost.Services
属性来获取服务提供者。 DbContext
本身及其构造函数中的任何依赖项都需要在应用程序的服务提供程序中注册为服务。这可以通过在DbContext
上使用构造函数来实现,该构造函数将DbContextOptions<TContext>
的实例作为参数并使用AddDbContext<TContext>
方法。DbContext
,则工具会在项目中查找派生的DbContext
类型。然后他们尝试使用没有参数的构造函数创建实例。如果使用DbContext
方法配置OnConfiguring
,则这可以是默认构造函数。DbContext
接口告诉工具如何创建IDesignTimeDbContextFactory<TContext>
:如果在与派生的DbContext相同的项目中或在应用程序的启动项目中找到实现此接口的类,则这些工具会绕过创建DbContext
并使用设计时工厂。当我在向dbcontext提供选项的同时将dbcontext添加到以下服务时,我遇到了同样的问题: -
services.AddDbContext<TodoContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
然后我添加了dbcontext没有像下面这样的选项,它解决了我的问题
services.AddDbContext<TodoContext>();
我还必须将onConfiguring方法添加到dbcontext类,以便上下文可以访问连接字符串: -
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=IdenDB;Trusted_Connection=True;MultipleActiveResultSets=true");
}
我不确定这是否是正确的做事方式,因为我刚开始使用核心,但here是一个答案,可以更详细地解释这个问题