如何在多个应用中共享一个EF Core DbContext?
我之前帮不少开发者排查过类似的迁移问题,你遇到的情况核心原因大多是DI生命周期不匹配或者DbContext配置没适配ASP.NET Core环境,下面给你一步步拆解解决方案:
1. 先把DbContext正确注册到ASP.NET Core的DI容器
原来的WCF可能依赖app.config或者硬编码配置DbContext,但ASP.NET Core用的是全新的配置体系,你得先把DbContext按规范注册:
在Startup.cs的ConfigureServices方法中,用AddDbContext注册,同时从appsettings.json读取连接字符串:
public void ConfigureServices(IServiceCollection services) { // 注册DbContext,指定数据库提供程序和连接字符串 services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AppDbConnection"))); // 其他ASP.NET Core服务配置(比如MVC等) services.AddMvc(); }
然后在appsettings.json里配置和原WCF一致的连接字符串:
{ "ConnectionStrings": { "AppDbConnection": "Server=你的数据库地址;Database=你的数据库名;Trusted_Connection=True;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning" } } }
2. 调整WCF服务的生命周期,避免和DbContext冲突
这是最容易踩坑的点:如果你的WCF服务原来配置的是单例模式(比如WCF里的InstanceContextMode.Single),在ASP.NET Core里绝对不能用AddSingleton注册它!
DbContext的默认生命周期是Scoped(每个请求对应一个实例),单例服务会一直持有同一个DbContext实例,时间久了这个实例会被释放或状态异常,自然查不到数据。你得把WCF服务注册为Scoped或者Transient:
// 把WCF服务注册为Scoped,和DbContext生命周期匹配 services.AddScoped<I你的WCF接口, 你的WCF服务实现类>();
3. 把WCF服务的DbContext获取方式改成构造函数注入
原来的WCF服务可能直接new AppDbContext()创建实例,这在ASP.NET Core的DI体系里是大忌——自己new的DbContext不会读取ASP.NET Core的配置,相当于用了错误的连接字符串,当然查不到数据。
你得改成构造函数注入,让DI容器给你传正确的DbContext实例:
public class 你的WCF服务实现类 : I你的WCF接口 { private readonly AppDbContext _dbContext; // 构造函数接收DbContext,不要自己new! public 你的WCF服务实现类(AppDbContext dbContext) { _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); } // 业务方法里直接使用注入的_dbContext查询 public List<你的实体类> GetData() { return _dbContext.你的实体集合.ToList(); } }
4. 检查AppDbContext的OnConfiguring方法
如果你的AppDbContext里写了OnConfiguring方法,一定要加个判断,确保ASP.NET Core的配置优先生效:
public class AppDbContext : DbContext { // 保留带参数的构造函数,让DI容器能注入配置 public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { // 只有当没有外部配置时,才用硬编码的连接字符串(兼容原WCF场景) if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer("原WCF使用的连接字符串"); } } }
最后验证
做完上面几步后重启应用,调用API试试。如果还是有问题,可以在服务方法里加日志输出_dbContext.Database.GetConnectionString(),确认是否指向正确的数据库——连接字符串不对的话肯定查不到数据。
内容的提问来源于stack exchange,提问作者rilly009

