Web API项目使用dotnet-ef创建迁移时遇DbContext激活错误
问题场景
执行EF迁移命令时触发错误:
dotnet ef migrations add "Add Identity Schema" --project ../src/api/migrations/MSSQL/ --context IdentityDbContext -o Identity
错误提示:
Unable to create a 'DbContext' of type 'TodoDbContext'. The exception 'Unable to resolve service for type 'Finbuckle.MultiTenant.Abstractions.IMultiTenantContextAccessor`1[App.Framework.Infrastructure.Tenant.appTenantInfo]' while attempting to activate 'App.WebApi.Todo.Persistence.TodoDbContext'.' was thrown while attempting to create an instance. For the different patterns supported at design time
核心问题:激活TodoDbContext时,无法解析IMultiTenantContextAccessor服务。
解决方案
方案1:添加设计时DbContext工厂
创建实现IDesignTimeDbContextFactory<TodoDbContext>的类,手动模拟租户依赖并配置上下文:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Finbuckle.MultiTenant.Abstractions; using Finbuckle.MultiTenant; public class TodoDbContextDesignTimeFactory : IDesignTimeDbContextFactory<TodoDbContext> { public TodoDbContext CreateDbContext(string[] args) { // 模拟租户上下文,按需填充实际租户属性 var mockTenantContext = new MultiTenantContext<appTenantInfo> { TenantInfo = new appTenantInfo { ConnectionString = "你的设计时数据库连接字符串" } }; var tenantAccessor = new Mock<IMultiTenantContextAccessor<appTenantInfo>>(); tenantAccessor.Setup(t => t.MultiTenantContext).Returns(mockTenantContext); var optionsBuilder = new DbContextOptionsBuilder<TodoDbContext>(); optionsBuilder.UseSqlServer(mockTenantContext.TenantInfo.ConnectionString); return new TodoDbContext(optionsBuilder.Options, tenantAccessor.Object); } }
注:需安装Moq包实现模拟,也可手动写一个空的IMultiTenantContextAccessor实现类替代。
方案2:明确指定目标DbContext
命令目标是IdentityDbContext,但EF误激活了TodoDbContext,可尝试:
- 确认
IdentityDbContext未依赖TodoDbContext或租户服务 - 命令中使用完整命名空间指定上下文,避免歧义:
dotnet ef migrations add "Add Identity Schema" --project ../src/api/migrations/MSSQL/ --context 你的命名空间.IdentityDbContext -o Identity
方案3:临时添加设计时构造函数
给TodoDbContext添加仅用于设计时的无参构造函数,手动配置连接:
public TodoDbContext() { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer("你的设计时数据库连接字符串"); } }
注:迁移完成后建议移除或注释该构造函数,避免影响生产环境。
内容的提问来源于stack exchange,提问作者Hadi Ansari

