.NET Core 6跨项目配置EF Core迁移及DbContext注入报错求助
解决EF Core 7迁移报错及进阶配置方案
一、解决当前迁移报错问题
报错核心原因是EF Core设计时工具无法解析DbContextOptions<MyDbContext>,因为DbContext位于类库项目,迁移工具默认无法读取Web API项目中的服务配置。以下两种方式可解决:
方式1:迁移时指定启动项目
执行迁移命令时,明确指定启动项目(Web API项目)和目标项目(类库项目),让工具加载Web项目的配置:
使用Dotnet CLI
# 假设类库项目目录为 MyEFCoreTestProject.EntityFrameworkCore,Web API项目在上级目录的 MyEFCoreTestProject.WebApi 下 dotnet ef migrations add InitialCreate --startup-project ../MyEFCoreTestProject.WebApi --project . dotnet ef database update --startup-project ../MyEFCoreTestProject.WebApi --project .
使用Package Manager Console(Visual Studio)
Add-Migration InitialCreate -StartupProject MyEFCoreTestProject.WebApi -Project MyEFCoreTestProject.EntityFrameworkCore Update-Database -StartupProject MyEFCoreTestProject.WebApi -Project MyEFCoreTestProject.EntityFrameworkCore
方式2:添加设计时DbContext工厂
在类库项目中创建实现IDesignTimeDbContextFactory<MyDbContext>的类,让迁移工具直接通过该工厂创建DbContext实例:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; public class MyDbContextDesignTimeFactory : IDesignTimeDbContextFactory<MyDbContext> { public MyDbContext CreateDbContext(string[] args) { // 加载Web项目的appsettings.json获取连接字符串 var configuration = new ConfigurationBuilder() .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../MyEFCoreTestProject.WebApi")) .AddJsonFile("appsettings.json") .Build(); var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>(); optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection")); return new MyDbContext(optionsBuilder.Options); } }
添加后直接在类库项目目录执行迁移命令即可,无需额外指定启动项目。
二、进阶:可动态传入参数的DbContext配置方案
方案1:自定义DbContext构造函数(支持传入连接字符串)
修改MyDbContext,保留依赖注入用的构造函数,同时添加支持手动传入连接字符串的构造函数:
using Core; using Microsoft.EntityFrameworkCore; public class MyDbContext : DbContext { // 用于依赖注入的构造函数(保留) public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { } // 用于手动传入连接字符串的构造函数 public MyDbContext(string connectionString) : base(GetOptions(connectionString)) { } private static DbContextOptions<MyDbContext> GetOptions(string connectionString) { return new DbContextOptionsBuilder<MyDbContext>() .UseSqlServer(connectionString) .Options; } public DbSet<Customer> Customers{ get; set; } public DbSet<CustomerAddress> CustomerAddresses { get; set; } }
使用时可手动实例化:
var dbContext = new MyDbContext("Your_Connection_String_Here");
方案2:使用DbContextFactory(推荐)
.NET 6中推荐用IDbContextFactory<TContext>管理DbContext生命周期,适合动态传参场景:
1. 注册DbContextFactory
在Web API项目的Program.cs中添加注册:
builder.Services.AddDbContextFactory<MyDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
2. 注入并使用工厂
在服务中注入IDbContextFactory<MyDbContext>,按需创建DbContext实例:
public class CustomerService { private readonly IDbContextFactory<MyDbContext> _dbContextFactory; public CustomerService(IDbContextFactory<MyDbContext> dbContextFactory) { _dbContextFactory = dbContextFactory; } public async Task<Customer> GetCustomerById(int id) { using var dbContext = _dbContextFactory.CreateDbContext(); return await dbContext.Customers.FindAsync(id); } }
3. 自定义动态参数工厂
若需动态传入连接字符串等参数,可创建自定义工厂:
public class MyDynamicDbContextFactory { public MyDbContext CreateDbContext(string connectionString) { var options = new DbContextOptionsBuilder<MyDbContext>() .UseSqlServer(connectionString) .Options; return new MyDbContext(options); } }
注册该工厂:
builder.Services.AddScoped<MyDynamicDbContextFactory>();
使用时传入参数创建实例:
public class CustomerService { private readonly MyDynamicDbContextFactory _dbContextFactory; public CustomerService(MyDynamicDbContextFactory dbContextFactory) { _dbContextFactory = dbContextFactory; } public async Task<Customer> GetCustomerById(string connectionString, int id) { using var dbContext = _dbContextFactory.CreateDbContext(connectionString); return await dbContext.Customers.FindAsync(id); } }
内容的提问来源于stack exchange,提问作者user21148869
相关产品推荐
相关产品推荐

