WPF中Entity Framework依赖注入时出现对象引用异常
问题分析与解决方案
问题根源
你的LoginViewModel被注册为Singleton单例生命周期,但KnitterNotebookContext默认是Scoped作用域生命周期。单例依赖作用域服务会导致DI容器无法正确解析:作用域服务需要在活动作用域内创建,而单例初始化时没有可用的作用域,最终引发对象引用异常。此外,若LoginWindow的DataContext是手动实例化而非DI注入,也会导致依赖缺失。
具体解决方案
1. 统一服务生命周期
将LoginWindow和LoginViewModel的注册改为Scoped,与DbContext的默认生命周期匹配:
.ConfigureServices((hostContext, services) => { // 替换Singleton为Scoped,与DbContext生命周期对齐 services.AddScoped<LoginWindow>(); services.AddScoped<LoginViewModel>(); services.AddDbContext<KnitterNotebookContext>( options => { // 推荐使用Host内置配置系统读取连接字符串,替代手动JSON解析 var connectionString = hostContext.Configuration.GetConnectionString("KnitterNotebookConnectionString"); options.UseSqlServer(connectionString); }); })
2. 启动时创建作用域获取服务
修改OnStartup方法,通过创建服务作用域来解析Scoped类型的窗口:
protected override async void OnStartup(StartupEventArgs e) { await AppHost!.StartAsync(); // 创建作用域以正确解析Scoped服务 using var scope = AppHost.Services.CreateScope(); var startupWindow = scope.ServiceProvider.GetRequiredService<LoginWindow>(); startupWindow.Show(); base.OnStartup(e); }
3. 确保窗口通过DI注入ViewModel
修改LoginWindow的构造函数,接收LoginViewModel并设置为DataContext,避免手动实例化:
public partial class LoginWindow : Window { public LoginWindow(LoginViewModel viewModel) { InitializeComponent(); DataContext = viewModel; } }
4. 优化连接字符串配置(可选)
在appsettings.json中配置连接字符串,让Host自动读取:
{ "ConnectionStrings": { "KnitterNotebookConnectionString": "你的SQL Server连接字符串" } }
同时确保appsettings.json的复制到输出目录属性设置为始终复制,避免运行时找不到文件。
内容的提问来源于stack exchange,提问作者JakubCzura
相关产品推荐
相关产品推荐

