You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF .NET6项目中DbContextFactory调用CreateDbContext()空异常排查

问题分析与修复方案

核心问题:_contextFactory未被依赖注入赋值

你在MainWindow中声明了_contextFactory字段,但没有通过依赖注入获取实例。因为你注册了MainWindow为瞬态服务,但使用的是无参构造函数,DI容器无法自动注入IDbContextFactory<MyDbContext>,导致_contextFactory始终为null,调用CreateDbContext()时触发空引用异常。

次要问题:MyDbContext.OnConfiguring代码冗余/错误

当optionsBuilder未配置时,你新建了DbContextOptionsBuilder实例但未将配置应用到传入的optionsBuilder上,属于无效代码。

MVVM架构优化建议

当前在Window中创建DbContext再传递给ViewModel的方式不符合职责分离原则,应将IDbContextFactory<MyDbContext>直接注入到ViewModel中,由ViewModel自行管理DbContext生命周期。


修复步骤

1. 修复MainWindow的依赖注入

修改MainWindow构造函数,通过构造函数注入IDbContextFactory<MyDbContext>:

public partial class MainWindow : Window
{
    private readonly IDbContextFactory<MyDbContext> _contextFactory;
    private SomeViewModel _someViewModel;

    // 通过构造函数注入工厂实例
    public MainWindow(IDbContextFactory<MyDbContext> contextFactory)
    {
        InitializeComponent();
        _contextFactory = contextFactory;

        // 直接将工厂传入ViewModel(更符合MVVM)
        _someViewModel = new SomeViewModel(contextFactory);
        DataContext = _someViewModel;
    }
}

2. 修正MyDbContext的OnConfiguring方法

删除冗余的DbContextOptionsBuilder创建逻辑,直接修改传入的optionsBuilder:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        string defaultConnection = Settings.Default.DefaultConnection;
        // 直接使用传入的optionsBuilder配置数据库连接
        optionsBuilder.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection));
    }

    optionsBuilder.UseLazyLoadingProxies();
    optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
    optionsBuilder.EnableSensitiveDataLogging();
    optionsBuilder.EnableDetailedErrors();
}

3. 优化ViewModel的DbContext使用

将IDbContextFactory<MyDbContext>注入到ViewModel,由ViewModel自行创建DbContext:

public class SomeViewModel
{
    private readonly IDbContextFactory<MyDbContext> _contextFactory;

    public SomeViewModel(IDbContextFactory<MyDbContext> contextFactory)
    {
        _contextFactory = contextFactory;
    }

    // 示例:使用工厂创建DbContext并执行数据操作
    public async Task LoadDataAsync()
    {
        using var context = _contextFactory.CreateDbContext();
        // 执行数据查询/操作,例如:
        // var dataList = await context.YourDbSet.ToListAsync();
    }
}

4. 确保服务提供者正确构建并启动应用

在App.xaml.cs中,必须从DI容器中获取MainWindow实例启动,而非直接new:

public partial class App : Application
{
    private IServiceProvider _serviceProvider;

    protected override void OnStartup(StartupEventArgs e)
    {
        var services = new ServiceCollection();
        ConfigureServices(services);
        _serviceProvider = services.BuildServiceProvider();

        // 从容器中获取MainWindow实例,触发依赖注入
        var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
        mainWindow.Show();
    }

    private void ConfigureServices(IServiceCollection services)
    {
        string defaultConnection = Settings.Default.DefaultConnection;

        services.AddDbContextFactory<MyDbContext>(options => 
            options.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection)));

        services.AddTransient<MainWindow>();
        // 注册ViewModel到DI容器
        services.AddTransient<SomeViewModel>();
    }
}

内容的提问来源于stack exchange,提问作者Donatas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:25:15