EF Core 6/7:派生DbContext的正确注入与双向访问方案
EF Core中继承DbContext的双向注入解决方案
问题场景
我有一个基础类库,其中包含带有日志、设置等基础实体的BaseContext类,在具体项目中继承它得到ProjectContext以实现项目特定逻辑:
BaseContext代码
public class BaseContext : DbContext { public BaseContext(DbContextOptions<BaseContext> options) : base(options) { } }
ProjectContext代码
public class ProjectContext: BaseContext { public ProjectContext(DbContextOptions<BaseContext> options) : base(options) { } public ProjectContext(DbContextOptions options) : base(options) { } }
上下文注册代码(Startup)
services.AddDbContext<ProjectContext>(options => { if (Helpers.IsDevelopment()) { options.EnableSensitiveDataLogging(); options.EnableDetailedErrors(); } options.UseNpgsql(Configuration.GetConnectionString("Context"), b => { b.MigrationsAssembly("App.Project.Specific"); b.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); b.EnableRetryOnFailure(5); }); } );
依赖场景
基础库中的服务(如AssetsService)依赖BaseContext:
public AssetsService(BaseContext db,...)
错误信息
Unable to resolve service for type 'App.Shared.DataModel.BaseContext' while attempting to activate 'App.Shared.Services.AssetsService'
需要实现对BaseContext和ProjectContext的双向访问,解决依赖注入失败问题。
解决方案
1. 规范ProjectContext构造函数(可选)
修改ProjectContext的构造函数,使用泛型DbContextOptions<ProjectContext>,让EF Core正确识别上下文类型,同时兼容基类构造:
public class ProjectContext : BaseContext { public ProjectContext(DbContextOptions<ProjectContext> options) : base(options) { } }
2. 显式注册双向上下文服务
在Startup的服务配置中,先注册ProjectContext,再将其作为BaseContext的实现注入,确保两种类型都能被解析:
// 注册ProjectContext services.AddDbContext<ProjectContext>(options => { if (Helpers.IsDevelopment()) { options.EnableSensitiveDataLogging(); options.EnableDetailedErrors(); } options.UseNpgsql(Configuration.GetConnectionString("Context"), b => { b.MigrationsAssembly("App.Project.Specific"); b.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); b.EnableRetryOnFailure(5); }); }); // 将ProjectContext实例注册为BaseContext的服务 services.AddScoped<BaseContext>(provider => provider.GetRequiredService<ProjectContext>());
3. 效果验证
- 依赖
ProjectContext的类会直接获取项目特定的上下文实例 - 依赖
BaseContext的类(如AssetsService)会获取同一个ProjectContext实例,实现双向访问且共享数据库连接与事务
替代方案:使用AddDbContext重载直接关联基类
如果不想额外添加Scoped注册,可使用AddDbContext的重载同时指定基类与子类:
services.AddDbContext<ProjectContext, BaseContext>(options => { // 保持原有配置逻辑 });
注:该方式在部分EF Core版本中可能存在兼容性问题,优先推荐显式注册的方案。
内容的提问来源于stack exchange,提问作者nicknack123123
相关产品推荐
相关产品推荐

