ASP.NET Core 8 Web API执行Add-Migration时DbContext创建失败
ASP.NET Core 8 Web API Add-Migration 空引用异常解决
执行Add-Migration InitialMigrations命令时触发错误:
Unable to create a 'DbContext' of type 'AMSContext'. The exception 'Object reference not set to an instance of an object.' was thrown while attempting to create an instance.
相关代码片段
AMSContext.cs
public partial class AMSContext : BaseContext { private readonly ICurrentUser _currentUser; public AMSContext(DbContextOptions<AMSContext> options, ICurrentUser currentUser ) : base(options) { _currentUser = currentUser; } // Dbsets 定义 }
BaseContext.cs
public abstract class BaseContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, IdentityUserClaim<int>, IdentityUserRole<int>, IdentityUserLogin<int>, ApplicationRoleClaim, IdentityUserToken<int>> { protected BaseContext(DbContextOptions options) : base(options) { } }
Program.cs 配置
services.AddDbContext<AMSContext>(options => { options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), o => { o.CommandTimeout((int)TimeSpan.FromMinutes(2).TotalSeconds); o.MigrationsAssembly(Assembly.GetAssembly(typeofMSContext))!.FullName); }); options.EnableSensitiveDataLogging(); });
错误根源分析
- Program.cs语法错误:
Assembly.GetAssembly(typeofMSContext)存在语法错误,正确写法应为Assembly.GetAssembly(typeof(AMSContext)),缺失括号导致Assembly.GetAssembly返回null,后续!.FullName触发空引用异常。 - 设计时依赖缺失:EF Core设计时创建DbContext时,不会完整启动Web应用的服务容器,
ICurrentUser依赖无法被正常注入,也会导致实例化失败。
解决方案
方案1:修复Program.cs语法错误
修正迁移程序集配置的语法问题:
services.AddDbContext<AMSContext>(options => { options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), o => { o.CommandTimeout((int)TimeSpan.FromMinutes(2).TotalSeconds); // 修正typeof的语法 o.MigrationsAssembly(Assembly.GetAssembly(typeof(AMSContext))!.FullName); }); options.EnableSensitiveDataLogging(); });
方案2:添加设计时专用构造函数
在AMSContext中添加仅用于设计时的构造函数,传入模拟的ICurrentUser实现:
public partial class AMSContext : BaseContext { private readonly ICurrentUser _currentUser; // 运行时构造函数 public AMSContext(DbContextOptions<AMSContext> options, ICurrentUser currentUser) : base(options) { _currentUser = currentUser; } // 设计时构造函数 public AMSContext() : base(new DbContextOptionsBuilder<AMSContext>() .UseSqlServer("你的数据库连接字符串") .Options) { _currentUser = new MockCurrentUser(); } } // 模拟ICurrentUser实现 public class MockCurrentUser : ICurrentUser { public int UserId => 1; // 实现接口其他成员,返回默认值即可 }
方案3:实现IDesignTimeDbContextFactory
创建工厂类专门处理设计时DbContext实例化:
public class AMSContextDesignTimeFactory : IDesignTimeDbContextFactory<AMSContext> { public AMSContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder<AMSContext>(); optionsBuilder.UseSqlServer("你的数据库连接字符串", o => { o.CommandTimeout((int)TimeSpan.FromMinutes(2).TotalSeconds); o.MigrationsAssembly(Assembly.GetAssembly(typeof(AMSContext))!.FullName); }); return new AMSContext(optionsBuilder.Options, new MockCurrentUser()); } }
方案4:设计时注册模拟服务
在Program.cs中判断设计时环境,注册ICurrentUser的模拟实现:
var isDesignTime = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" && Assembly.GetEntryAssembly()?.GetName().Name.Contains("DesignTime") == true; services.AddScoped<ICurrentUser>(sp => { if (isDesignTime) { return new MockCurrentUser(); } else { return new CurrentUserImplementation(); // 运行时真实实现 } });
内容的提问来源于stack exchange,提问作者Waleed Umer
相关产品推荐
相关产品推荐

